Debugging another memory bug.

This commit is contained in:
Kyle Isom 2023-10-09 19:59:21 -07:00
parent 85ff28360b
commit 8122ca265d
11 changed files with 253 additions and 43 deletions

View File

@ -13,6 +13,7 @@
#define PROT_RW (PROT_WRITE|PROT_READ)
#elif defined(__WIN64__) || defined(__WIN32__)
#include <Windows.h>
#include <fileapi.h>
#endif
@ -144,7 +145,47 @@ Arena::Create(const char *path, size_t fileSize, mode_t mode)
int
Arena::Open(const char *path)
{
HANDLE fHandle;
size_t fSize;
size_t fRead = 0;
size_t fRemaining;
auto cursor = this->store;
OVERLAPPED overlap;
fHandle = CreateFileA(
(LPSTR)path,
GENERIC_READ,
(FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE),
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (fHandle == INVALID_HANDLE_VALUE) {
return -1;
}
if (!GetFileSizeEx(fHandle, reinterpret_cast<PLARGE_INTEGER>(&fSize))) {
CloseHandle(fHandle);
return -1;
}
this->SetAlloc(fSize);
fRemaining = fSize;
while (fRemaining != 0) {
overlap.Offset = (fSize - fRemaining);
if (!ReadFile(fHandle, cursor, fSize, reinterpret_cast<LPDWORD>(&fRead), &overlap)) {
CloseHandle(fHandle);
this->Destroy();
return -1;
}
cursor += fRead;
fRemaining -= fRead;
}
CloseHandle(fHandle);
return 0;
}
#endif
@ -227,7 +268,7 @@ operator<<(std::ostream &os, Arena &arena)
{
auto cursor = arena.Store();
char cursorString[33] = {0};
snprintf(cursorString, 32, "%#016lx", cursor);
snprintf(cursorString, 32, "%#016llx", cursor);
os << "Arena<";
switch (arena.Type()) {

View File

@ -1,3 +1,9 @@
/// @file Arena.h
/// @author K. Isom
/// @brief Memory management using an arena.
/// @section DESCRIPTION
/// Arena defines a memory management backend for pre-allocating memory.
#ifndef KIMODEM_ARENA_H
#define KIMODEM_ARENA_H
@ -41,6 +47,8 @@ public:
int MemoryMap(int memFileDes, size_t memSize); // Arena will own fd.
int Create(const char *path, size_t fileSize, mode_t mode);
int Open(const char *path);
#elif defined(__WIN64__) || defined(__WIN32__)
int Open(const char *path);
#endif
uint8_t *NewCursor() const { return this->store; }

View File

@ -4,8 +4,11 @@
#include <cassert>
#include <cstring>
#include "Buffer.h"
#include <ios>
#include <iostream>
#include <iomanip>
#include "Buffer.h"
namespace klib {
@ -140,7 +143,7 @@ void
Buffer::Resize(size_t newCapacity)
{
if (newCapacity < this->length) {
return;
newCapacity = nearestPower(this->length + newCapacity);
}
auto newContents = new uint8_t[newCapacity];
@ -151,6 +154,7 @@ Buffer::Resize(size_t newCapacity)
}
delete this->contents;
this->contents = nullptr;
this->contents = newContents;
this->capacity = newCapacity;
}
@ -183,15 +187,23 @@ Buffer::Clear()
void
Buffer::Reclaim()
{
std::cout << "clear" << std::endl;
this->Clear();
std::cout << "nullptr check" << std::endl;
if (this->contents == nullptr) {
std::cout << "assert checks" << std::endl;
assert(this->length == 0);
assert(this->capacity == 0);
return;
}
std::cout << "delete " << this->Capacity() << "B" << std::endl;
this->HexDump(std::cout);
delete this->contents;
std::cout << "reset contents" << std::endl;
this->contents = nullptr;
std::cout << "reset capacity" << std::endl;
this->capacity = 0;
}
@ -207,6 +219,42 @@ Buffer::mustGrow(size_t delta) const
}
void
Buffer::HexDump(std::ostream &os)
{
#ifndef NDEBUG
size_t index = 0;
os << std::hex;
os << std::setfill('0');
for (index = 0; index < this->length; index++) {
bool eol = (index % 16) == 0;
if (eol && (index > 0)) {
os << std::endl;
}
if (eol) {
os << std::setw(8);
os << index << " ";
os << std::setw(2);
}
os << (unsigned short)this->contents[index];
if ((index % 15) != 0 || (index == 0)) {
os << " ";
}
}
if ((index % 16) != 0) {
os << std::endl;
}
os << std::setw(0) << std::dec;
#endif
}
bool
Buffer::shiftRight(size_t offset, size_t delta)
{

View File

@ -5,6 +5,7 @@
#ifndef KGE_BUFFER_H
#define KGE_BUFFER_H
#include <iostream>
#include <cstdint>
@ -39,6 +40,8 @@ public:
void Clear();
void Reclaim();
void HexDump(std::ostream &os);
uint8_t &operator[](size_t index);
private:
size_t mustGrow(size_t delta) const;

10
CMakeDocs.txt Normal file
View File

@ -0,0 +1,10 @@
# Doxygen support for klib.
find_package(Doxygen)
if (${DOXYGEN_FOUND})
doxygen_add_docs(klib_docs
${HEADER_FILES} ${SOURCE_FILES}
USE_STAMP_FILE)
endif ()

View File

@ -19,13 +19,22 @@ set(HEADER_FILES
Arena.h
Buffer.h
Dictionary.h
Test.h
TLV.h)
set(SOURCE_FILES
Arena.cc
Buffer.cc
Dictionary.cc
Test.cc
TLV.cc)
add_library(klib STATIC
Arena.cc
Buffer.cc
Dictionary.cc
TLV.cc)
TLV.cc
)
install(TARGETS klib LIBRARY DESTINATION ${PREFIX}/lib)
install(FILES ${HEADER_FILES} DESTINATION include/klib)
install(FILES klibConfig.cmake DESTINATION share/klib/cmake)
@ -45,11 +54,12 @@ add_executable(buffer_test bufferTest.cc)
target_link_libraries(buffer_test klib)
add_test(bufferTest buffer_test)
include(CMakePack.txt)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
klibConfig.cmake
VERSION ${PACKAGE_VERSION}
COMPATIBILITY AnyNewerVersion
)
include(CMakePack.txt)
include(CMakeDocs.txt)

42
Test.cc Normal file
View File

@ -0,0 +1,42 @@
//
// Created by kyle on 2023-10-09.
//
#include "Test.h"
#include <iostream>
#include <cassert>
namespace klib {
void
TestAssert(bool condition, std::string message = "Assertion failed.")
{
#if defined(NDEBUG)
if (!condition) {
throw AssertionFailed(message);
}
#else
if (!condition) {
std::cerr << message << std::endl;
}
assert(condition);
#endif
}
AssertionFailed::AssertionFailed(std::string message) : msg(message)
{
}
char *
AssertionFailed::what() const noexcept
{
return const_cast<char *>(this->msg.c_str());
}
} // namespace klib

31
Test.h Normal file
View File

@ -0,0 +1,31 @@
//
// Created by kyle on 2023-10-09.
//
#include <string>
#ifndef KLIB_TEST_H
#define KLIB_TEST_H
namespace klib {
void
TestAssert(bool condition, std::string message);
class AssertionFailed : public std::exception {
public:
explicit AssertionFailed(std::string message);
char *what() const noexcept override;
public:
std::string msg;
};
} // namespace klib
#endif //KLIB_TEST_H

View File

@ -18,12 +18,26 @@ main(int argc, char *argv[])
std::cout << buffer.Contents() << std::endl;
std::cout << "remove end" << std::endl;
buffer.Remove(buffer.Length() - 1);
buffer.Remove(0, 5);
buffer.Insert(0, 'g');
buffer.Insert(1, (uint8_t *) "oodbye", 6);
std::cout << "remove start" << std::endl;
buffer.Remove(0, 5);
std::cout << "insert char" << std::endl;
buffer.Insert(0, 'g');
std::cout << "insert chunk" << std::endl;
buffer.Insert(1, (uint8_t *) "oodbye", 6);
std::cout << "cruel" << std::endl;
buffer.Insert(9, (uint8_t *)"cruel ", 6);
std::cout << buffer.Contents() << std::endl;
buffer.HexDump(std::cout);
std::cout << "reclaim" << std::endl;
buffer.Reclaim();
std::cout << "append" << std::endl;
buffer.Append("and now for something completely different...");
std::cout << buffer.Contents() << std::endl;

View File

@ -48,7 +48,7 @@ main(int argc, const char *argv[])
abort();
}
#else
if (AllocNewArena(arena, ARENA_SIZE) == -1) {
if (arena.SetAlloc(ARENA_SIZE) == -1) {
abort();
}
#endif

View File

@ -4,10 +4,13 @@
#include <iostream>
#include "Arena.h"
#include "Test.h"
#include "TLV.h"
#include "testFixtures.h"
using namespace klib;
static uint8_t arenaBuffer[ARENA_SIZE];