Debugging another memory bug.
This commit is contained in:
parent
85ff28360b
commit
8122ca265d
43
Arena.cc
43
Arena.cc
|
@ -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()) {
|
||||||
|
|
8
Arena.h
8
Arena.h
|
@ -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; }
|
||||||
|
|
52
Buffer.cc
52
Buffer.cc
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
3
Buffer.h
3
Buffer.h
|
@ -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;
|
||||||
|
|
|
@ -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 ()
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue