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) #define PROT_RW (PROT_WRITE|PROT_READ)
#elif defined(__WIN64__) || defined(__WIN32__) #elif defined(__WIN64__) || defined(__WIN32__)
#include <Windows.h>
#include <fileapi.h> #include <fileapi.h>
#endif #endif
@ -144,7 +145,47 @@ Arena::Create(const char *path, size_t fileSize, mode_t mode)
int int
Arena::Open(const char *path) 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 #endif
@ -227,7 +268,7 @@ operator<<(std::ostream &os, Arena &arena)
{ {
auto cursor = arena.Store(); auto cursor = arena.Store();
char cursorString[33] = {0}; char cursorString[33] = {0};
snprintf(cursorString, 32, "%#016lx", cursor); snprintf(cursorString, 32, "%#016llx", cursor);
os << "Arena<"; os << "Arena<";
switch (arena.Type()) { 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 #ifndef KIMODEM_ARENA_H
#define KIMODEM_ARENA_H #define KIMODEM_ARENA_H
@ -41,6 +47,8 @@ public:
int MemoryMap(int memFileDes, size_t memSize); // Arena will own fd. int MemoryMap(int memFileDes, size_t memSize); // Arena will own fd.
int Create(const char *path, size_t fileSize, mode_t mode); int Create(const char *path, size_t fileSize, mode_t mode);
int Open(const char *path); int Open(const char *path);
#elif defined(__WIN64__) || defined(__WIN32__)
int Open(const char *path);
#endif #endif
uint8_t *NewCursor() const { return this->store; } uint8_t *NewCursor() const { return this->store; }

View File

@ -4,8 +4,11 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Buffer.h" #include <ios>
#include <iostream> #include <iostream>
#include <iomanip>
#include "Buffer.h"
namespace klib { namespace klib {
@ -34,7 +37,7 @@ nearestPower(size_t x)
std::cout << x + 1 << std::endl; std::cout << x + 1 << std::endl;
return x+1; return x + 1;
} }
@ -57,7 +60,7 @@ Buffer::Buffer(const char *data)
{ {
size_t datalen = strnlen(data, maxReasonableLine); size_t datalen = strnlen(data, maxReasonableLine);
this->Append((uint8_t *)data, datalen); this->Append((uint8_t *) data, datalen);
} }
@ -66,7 +69,7 @@ Buffer::Append(const char *s)
{ {
size_t slen = strnlen(s, maxReasonableLine); size_t slen = strnlen(s, maxReasonableLine);
return this->Append((uint8_t *)s, slen); return this->Append((uint8_t *) s, slen);
} }
bool bool
@ -98,7 +101,7 @@ Buffer::Insert(size_t index, const char *s)
{ {
size_t slen = strnlen(s, maxReasonableLine); size_t slen = strnlen(s, maxReasonableLine);
return this->Insert(index, (uint8_t *)(s), slen); return this->Insert(index, (uint8_t *) (s), slen);
} }
@ -140,7 +143,7 @@ void
Buffer::Resize(size_t newCapacity) Buffer::Resize(size_t newCapacity)
{ {
if (newCapacity < this->length) { if (newCapacity < this->length) {
return; newCapacity = nearestPower(this->length + newCapacity);
} }
auto newContents = new uint8_t[newCapacity]; auto newContents = new uint8_t[newCapacity];
@ -151,6 +154,7 @@ Buffer::Resize(size_t newCapacity)
} }
delete this->contents; delete this->contents;
this->contents = nullptr;
this->contents = newContents; this->contents = newContents;
this->capacity = newCapacity; this->capacity = newCapacity;
} }
@ -183,15 +187,23 @@ Buffer::Clear()
void void
Buffer::Reclaim() Buffer::Reclaim()
{ {
std::cout << "clear" << std::endl;
this->Clear(); this->Clear();
std::cout << "nullptr check" << std::endl;
if (this->contents == nullptr) { if (this->contents == nullptr) {
std::cout << "assert checks" << std::endl;
assert(this->length == 0); assert(this->length == 0);
assert(this->capacity == 0); assert(this->capacity == 0);
return; return;
} }
std::cout << "delete " << this->Capacity() << "B" << std::endl;
this->HexDump(std::cout);
delete this->contents; delete this->contents;
std::cout << "reset contents" << std::endl;
this->contents = nullptr; this->contents = nullptr;
std::cout << "reset capacity" << std::endl;
this->capacity = 0; 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 bool
Buffer::shiftRight(size_t offset, size_t delta) Buffer::shiftRight(size_t offset, size_t delta)
{ {
@ -220,7 +268,7 @@ Buffer::shiftRight(size_t offset, size_t delta)
if (this->length == 0) return 0; if (this->length == 0) return 0;
memmove(this->contents+(offset+delta), this->contents+offset, this->length); memmove(this->contents + (offset + delta), this->contents + offset, this->length);
return resized; return resized;
} }
@ -232,13 +280,13 @@ Buffer::shiftLeft(size_t offset, size_t delta)
// this->contents[i] = this->contents[i+delta]; // this->contents[i] = this->contents[i+delta];
// } // }
memmove(this->contents+offset, this->contents+(offset+delta), this->length); memmove(this->contents + offset, this->contents + (offset + delta), this->length);
return this->Trim() != 0; return this->Trim() != 0;
} }
uint8_t& uint8_t &
Buffer::operator[](size_t index) Buffer::operator[](size_t index)
{ {
return this->contents[index]; return this->contents[index];

View File

@ -5,6 +5,7 @@
#ifndef KGE_BUFFER_H #ifndef KGE_BUFFER_H
#define KGE_BUFFER_H #define KGE_BUFFER_H
#include <iostream>
#include <cstdint> #include <cstdint>
@ -39,6 +40,8 @@ public:
void Clear(); void Clear();
void Reclaim(); void Reclaim();
void HexDump(std::ostream &os);
uint8_t &operator[](size_t index); uint8_t &operator[](size_t index);
private: private:
size_t mustGrow(size_t delta) const; 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 Arena.h
Buffer.h Buffer.h
Dictionary.h Dictionary.h
Test.h
TLV.h) TLV.h)
set(SOURCE_FILES
Arena.cc
Buffer.cc
Dictionary.cc
Test.cc
TLV.cc)
add_library(klib STATIC add_library(klib STATIC
Arena.cc Arena.cc
Buffer.cc Buffer.cc
Dictionary.cc Dictionary.cc
TLV.cc) TLV.cc
)
install(TARGETS klib LIBRARY DESTINATION ${PREFIX}/lib) install(TARGETS klib LIBRARY DESTINATION ${PREFIX}/lib)
install(FILES ${HEADER_FILES} DESTINATION include/klib) install(FILES ${HEADER_FILES} DESTINATION include/klib)
install(FILES klibConfig.cmake DESTINATION share/klib/cmake) install(FILES klibConfig.cmake DESTINATION share/klib/cmake)
@ -45,11 +54,12 @@ add_executable(buffer_test bufferTest.cc)
target_link_libraries(buffer_test klib) target_link_libraries(buffer_test klib)
add_test(bufferTest buffer_test) add_test(bufferTest buffer_test)
include(CMakePack.txt)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
write_basic_package_version_file( write_basic_package_version_file(
klibConfig.cmake klibConfig.cmake
VERSION ${PACKAGE_VERSION} VERSION ${PACKAGE_VERSION}
COMPATIBILITY AnyNewerVersion 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 << buffer.Contents() << std::endl;
std::cout << "remove end" << std::endl;
buffer.Remove(buffer.Length() - 1); 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(); buffer.Reclaim();
std::cout << "append" << std::endl;
buffer.Append("and now for something completely different..."); buffer.Append("and now for something completely different...");
std::cout << buffer.Contents() << std::endl; std::cout << buffer.Contents() << std::endl;

View File

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

View File

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