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

12
Arena.h
View File

@ -38,14 +38,14 @@ public:
int SetAlloc(size_t allocSize);
#if defined(__linux__)
int MemoryMap(int fd); // Arena will own fd.
int Create(const char *path, size_t size, mode_t mode);
int Open(const char *, size_t);
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);
#endif
uint8_t *NewCursor() const { return this->store; }
uint8_t *End() { return this->store + this->size; }
bool CursorInArena(uint8_t *cursor);
bool CursorInArena(const uint8_t *cursor);
size_t Size() const
{ return this->size; }
@ -53,6 +53,8 @@ public:
uint8_t Type() const
{ return this->arenaType; }
uintptr_t Store() { return (uintptr_t)this->store; }
bool Ready() const { return this->Type() != ARENA_UNINIT; };
void Clear();
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

View File

@ -6,32 +6,33 @@
int
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;
buffer.Insert(1, (uint8_t *)"el", 2);
buffer.Insert(1, (uint8_t *) "el", 2);
buffer.Append('!');
std::cout << buffer.Contents() << 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);
buffer.Insert(1, (uint8_t *) "oodbye", 6);
buffer.Reclaim();
buffer.Append("and now for something completely different...");
std::cout << buffer.Contents() << std::endl;
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
buffer.Resize(128);
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
buffer.Trim();
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
buffer.Resize(128);
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
buffer.Trim();
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;
std::cout << "TESTPROG: " << argv[0] << std::endl;
InitializeArena(arena);
#if defined(__linux__)
if (CreateArena(arena, ARENA_FILE, ARENA_SIZE, 0644) == -1) {
if (arena.Create(ARENA_FILE, ARENA_SIZE, 0644) == -1) {
abort();
}
#else
@ -53,8 +52,7 @@ main(int argc, const char *argv[])
abort();
}
#endif
DisplayArena(arena);
std::cout << arena << std::endl;
TLV::SetRecord(expect, DICTIONARY_TAG_VAL, TEST_KVSTRLEN3, TEST_KVSTR3);
Dictionary dict(arena);
@ -101,6 +99,6 @@ main(int argc, const char *argv[])
dict.DumpToFile(ARENA_FILE);
#endif
ClearArena(arena);
arena.Clear();
dict.DumpKVPairs();
}

View File

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