Fix memory leak, start work on win file api.

This commit is contained in:
Kyle Isom 2023-10-09 16:20:26 -07:00
parent b2e0e849ef
commit 87fe9719c1
5 changed files with 84 additions and 75 deletions

110
Arena.cc
View File

@ -4,11 +4,16 @@
#include <cstring> #include <cstring>
#if defined(__linux__) #if defined(__linux__)
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#define PROT_RW (PROT_WRITE|PROT_READ)
#elif defined(__WIN64__) || defined(__WIN32__)
#include <fileapi.h>
#endif #endif
#include <ios> #include <ios>
@ -71,79 +76,81 @@ Arena::SetAlloc(size_t allocSize)
#if defined(__linux__) #if defined(__linux__)
int int
MMapArena(Arena &arena, int fd, size_t size) Arena::MemoryMap(int memFileDes, size_t memSize)
{ {
if (this->size > 0) { if (this->size > 0) {
if (DestroyArena(arena) != 0) { this->Destroy();
return -1;
}
} }
this->arenaType = ARENA_MMAP; this->arenaType = ARENA_MMAP;
this->size = size; this->size = memSize;
this->store = (uint8_t *)mmap(NULL, size, PROT_RW, MAP_SHARED, fd, 0); this->store = (uint8_t *) mmap(NULL, memSize, PROT_RW, MAP_SHARED,
if ((void *)this->store == MAP_FAILED) { memFileDes, 0);
if ((void *) this->store == MAP_FAILED) {
return -1; return -1;
} }
this->fd = fd; this->fd = memFileDes;
return 0; return 0;
} }
int int
OpenArena(Arena &arena, const char *path) Arena::Open(const char *path)
{ {
struct stat st; struct stat st{};
if (this->size > 0) { if (this->size > 0) {
if (DestroyArena(arena) != 0) { this->Destroy();
return -1;
}
} }
if (stat(path, &st) != 0) { if (stat(path, &st) != 0) {
return -1; return -1;
} }
this->fd = open(path, O_RDWR); this->fd = open(path, O_RDWR);
if (this->fd == -1) { if (this->fd == -1) {
return -1; return -1;
} }
return MMapArena(arena, this->fd, (size_t)st.st_size); return this->MemoryMap(this->fd, (size_t) st.st_size);
} }
int int
CreateArena(Arena &arena, const char *path, size_t size, mode_t mode) Arena::Create(const char *path, size_t fileSize, mode_t mode)
{ {
int fd = 0; int newFileDes = 0;
if (this->size > 0) { if (this->size > 0) {
if (DestroyArena(arena) != 0) { this->Destroy();
return -1;
}
} }
fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode); newFileDes = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
if (fd == -1) { if (newFileDes == -1) {
return -1; return -1;
} }
if (ftruncate(fd, size) == -1) { if (ftruncate(newFileDes, fileSize) == -1) {
return -1; return -1;
} }
close(fd); close(newFileDes);
return this->Open(path);
}
#elif defined(__WIN64__) || defined(__WIN32__)
int
Arena::Open(const char *path)
{
return OpenArena(arena, path);
} }
#endif #endif
bool bool
Arena::CursorInArena(uint8_t *cursor) Arena::CursorInArena(const uint8_t *cursor)
{ {
if (cursor < this->store) { if (cursor < this->store) {
return false; return false;
@ -186,25 +193,26 @@ Arena::Destroy()
case ARENA_ALLOC: case ARENA_ALLOC:
delete this->store; delete this->store;
break; break;
#if defined(__linux__) #if defined(__linux__)
case ARENA_MMAP: case ARENA_MMAP:
if (munmap(this->store, this->size) == -1) { if (munmap(this->store, this->size) == -1) {
return -1; abort();
} return;
}
if (close(this->fd) == -1) { if (close(this->fd) == -1) {
return -1; abort();
} }
this->fd = 0; this->fd = 0;
break; break;
#endif #endif
default: default:
#if defined(NDEBUG) #if defined(NDEBUG)
return -1; return -1;
#else #else
abort(); abort();
#endif #endif
} }
@ -215,11 +223,11 @@ Arena::Destroy()
} }
std::ostream & std::ostream &
operator<<(std::ostream &os, const Arena arena) operator<<(std::ostream &os, Arena &arena)
{ {
auto cursor = arena.NewCursor(); auto cursor = arena.Store();
char cursorString[17] = {0}; char cursorString[33] = {0};
snprintf(cursorString, 16, "%0p", cursor); snprintf(cursorString, 32, "%#016lx", cursor);
os << "Arena<"; os << "Arena<";
switch (arena.Type()) { switch (arena.Type()) {
@ -233,9 +241,9 @@ operator<<(std::ostream &os, const Arena arena)
os << "allocated"; os << "allocated";
break; break;
#if defined(__linux__) #if defined(__linux__)
case ARENA_MMAP: case ARENA_MMAP:
os << "mmap/file"; os << "mmap/file";
break; break;
#endif #endif
default: default:
os << "unknown (this is a bug)"; os << "unknown (this is a bug)";
@ -243,7 +251,7 @@ operator<<(std::ostream &os, const Arena arena)
os << ">@0x"; os << ">@0x";
os << std::hex << (uintptr_t) &arena; os << std::hex << (uintptr_t) &arena;
os << std::dec; os << std::dec;
os << ",store<" << arena.Size() << "B>@0x"; os << ",store<" << arena.Size() << "B>@";
os << std::hex << cursorString; os << std::hex << cursorString;
os << std::dec; os << std::dec;
@ -257,11 +265,11 @@ Arena::Write(const char *path)
FILE *arenaFile = NULL; FILE *arenaFile = NULL;
int retc = -1; int retc = -1;
#if defined(__posix__) #if defined(__posix__) || defined(__linux__)
arenaFile = fopen(path, "w"); arenaFile = fopen(path, "w");
if (arenaFile == NULL) { if (arenaFile == nullptr) {
#else #else
if (fopen_s(&arenaFile, path, "w") != 0) { if (fopen_s(&arenaFile, path, "w") != 0) {
#endif #endif
return -1; return -1;
} }

12
Arena.h
View File

@ -38,14 +38,14 @@ public:
int SetAlloc(size_t allocSize); int SetAlloc(size_t allocSize);
#if defined(__linux__) #if defined(__linux__)
int MemoryMap(int fd); // Arena will own fd. int MemoryMap(int memFileDes, size_t memSize); // Arena will own fd.
int Create(const char *path, size_t size, mode_t mode); int Create(const char *path, size_t fileSize, mode_t mode);
int Open(const char *, size_t); int Open(const char *path);
#endif #endif
uint8_t *NewCursor() const { return this->store; } uint8_t *NewCursor() const { return this->store; }
uint8_t *End() { return this->store + this->size; } uint8_t *End() { return this->store + this->size; }
bool CursorInArena(uint8_t *cursor); bool CursorInArena(const uint8_t *cursor);
size_t Size() const size_t Size() const
{ return this->size; } { return this->size; }
@ -53,6 +53,8 @@ public:
uint8_t Type() const uint8_t Type() const
{ return this->arenaType; } { return this->arenaType; }
uintptr_t Store() { return (uintptr_t)this->store; }
bool Ready() const { return this->Type() != ARENA_UNINIT; }; bool Ready() const { return this->Type() != ARENA_UNINIT; };
void Clear(); void Clear();
void Destroy(); /* dispose of any memory used by arena */ void Destroy(); /* dispose of any memory used by arena */
@ -74,7 +76,7 @@ private:
}; };
std::ostream &operator<<(std::ostream& os, Arena arena); std::ostream &operator<<(std::ostream& os, Arena &arena);
} // namespace klib } // namespace klib

View File

@ -6,32 +6,33 @@
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
(void)argc; (void)argv; (void) argc;
(void) argv;
klib::Buffer buffer("hlo, world"); klib::Buffer buffer("hlo, world");
std::cout << buffer.Contents() << std::endl; std::cout << buffer.Contents() << std::endl;
buffer.Insert(1, (uint8_t *)"el", 2); buffer.Insert(1, (uint8_t *) "el", 2);
buffer.Append('!'); buffer.Append('!');
std::cout << buffer.Contents() << std::endl; std::cout << buffer.Contents() << std::endl;
buffer.Remove(buffer.Length()-1); buffer.Remove(buffer.Length() - 1);
buffer.Remove(0, 5); buffer.Remove(0, 5);
buffer.Insert(0, 'g'); buffer.Insert(0, 'g');
buffer.Insert(1, (uint8_t *)"oodbye", 6); buffer.Insert(1, (uint8_t *) "oodbye", 6);
buffer.Reclaim(); buffer.Reclaim();
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;
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl; std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
buffer.Resize(128); buffer.Resize(128);
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl; std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
buffer.Trim(); buffer.Trim();
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl; std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
return 0; return 0;
} }

View File

@ -42,10 +42,9 @@ main(int argc, const char *argv[])
TLV::Record expect; TLV::Record expect;
std::cout << "TESTPROG: " << argv[0] << std::endl; std::cout << "TESTPROG: " << argv[0] << std::endl;
InitializeArena(arena);
#if defined(__linux__) #if defined(__linux__)
if (CreateArena(arena, ARENA_FILE, ARENA_SIZE, 0644) == -1) { if (arena.Create(ARENA_FILE, ARENA_SIZE, 0644) == -1) {
abort(); abort();
} }
#else #else
@ -53,8 +52,7 @@ main(int argc, const char *argv[])
abort(); abort();
} }
#endif #endif
DisplayArena(arena); std::cout << arena << std::endl;
TLV::SetRecord(expect, DICTIONARY_TAG_VAL, TEST_KVSTRLEN3, TEST_KVSTR3); TLV::SetRecord(expect, DICTIONARY_TAG_VAL, TEST_KVSTRLEN3, TEST_KVSTR3);
Dictionary dict(arena); Dictionary dict(arena);
@ -101,6 +99,6 @@ main(int argc, const char *argv[])
dict.DumpToFile(ARENA_FILE); dict.DumpToFile(ARENA_FILE);
#endif #endif
ClearArena(arena); arena.Clear();
dict.DumpKVPairs(); dict.DumpKVPairs();
} }

View File

@ -1,5 +1,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <exception>
#include <iostream> #include <iostream>
#include "Arena.h" #include "Arena.h"
@ -62,7 +63,7 @@ runSuite(Arena &backend, const char *label)
std::cout << "running test suite " << label << ": "; std::cout << "running test suite " << label << ": ";
try { try {
tlvTestSuite(backend); tlvTestSuite(backend);
} catch (_exception){ } catch (std::exception &exc){
std::cout << "FAILED" << std::endl; std::cout << "FAILED" << std::endl;
return false; return false;
} }
@ -95,9 +96,8 @@ main(int argc, const char *argv[])
#if defined(__linux__) #if defined(__linux__)
Arena arenaFile; Arena arenaFile;
InitializeArena(arenaFile);
if (-1 == CreateArena(arenaFile, ARENA_FILE, ARENA_SIZE, 0644)) { if (-1 == arenaFile.Create(ARENA_FILE, ARENA_SIZE, 0644)) {
abort(); abort();
} else if (!runSuite(arenaFile, "arenaFile")) { } else if (!runSuite(arenaFile, "arenaFile")) {
abort(); abort();