Fix memory leak, start work on win file api.
This commit is contained in:
parent
b2e0e849ef
commit
87fe9719c1
110
Arena.cc
110
Arena.cc
|
@ -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
12
Arena.h
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue