Store memory info in the allocated block, not as a separate block.

This will eventually enable us to get memory information in O(1) time.
Right now, we're still O(n) because MemoryInfoGet() still has to check to
see if the allocation is known or not.
This commit is contained in:
Jordan Bancino 2022-10-28 14:07:44 -04:00
parent 2791dbdcc8
commit bcff59bacb
3 changed files with 92 additions and 74 deletions

View file

@ -32,7 +32,6 @@ struct MemoryInfo
size_t size;
const char *file;
int line;
void *pointer;
MemoryInfo *next;
MemoryInfo *prev;
@ -46,30 +45,20 @@ static void *hookArgs = NULL;
void *
MemoryAllocate(size_t size, const char *file, int line)
{
void *p;
MemoryInfo *a;
pthread_mutex_lock(&lock);
p = malloc(size);
if (!p)
{
pthread_mutex_unlock(&lock);
return NULL;
}
a = malloc(sizeof(MemoryInfo));
a = malloc(sizeof(MemoryInfo) + size);
if (!a)
{
free(p);
pthread_mutex_unlock(&lock);
return NULL;
}
a->size = size;
a->size = sizeof(MemoryInfo) + size;
a->file = file;
a->line = line;
a->pointer = p;
a->next = NULL;
a->prev = lastAllocation;
@ -86,7 +75,7 @@ MemoryAllocate(size_t size, const char *file, int line)
}
pthread_mutex_unlock(&lock);
return p;
return MemoryInfoGetPointer(a);
}
void *
@ -95,34 +84,55 @@ MemoryReallocate(void *p, size_t size)
MemoryInfo *a;
void *new = NULL;
a = MemoryInfoGet(p);
if (!a)
{
if (hook)
{
hook(MEMORY_BAD_POINTER, NULL, hookArgs);
}
pthread_mutex_unlock(&lock);
return NULL;
}
pthread_mutex_lock(&lock);
a = lastAllocation;
while (a)
new = realloc(a, sizeof(MemoryInfo) + size);
if (!new)
{
if (a->pointer == p)
pthread_mutex_unlock(&lock);
return NULL;
}
a = new;
a->size = sizeof(MemoryInfo) + size;
if (a->prev)
{
new = realloc(p, size);
if (new)
a->prev->next = a;
}
else
{
a->pointer = new;
a->size = size;
lastAllocation = a;
}
if (a->next)
{
a->next->prev = a;
}
else
{
lastAllocation = a;
}
if (hook)
{
hook(MEMORY_REALLOCATE, a, hookArgs);
}
}
break;
}
a = a->prev;
}
pthread_mutex_unlock(&lock);
return new;
return MemoryInfoGetPointer(a);
}
void
@ -132,12 +142,17 @@ MemoryFree(void *p)
pthread_mutex_lock(&lock);
a = lastAllocation;
a = MemoryInfoGet(p);
if (!a)
{
if (hook)
{
hook(MEMORY_BAD_POINTER, NULL, hookArgs);
}
pthread_mutex_unlock(&lock);
return;
}
while (a)
{
if (a->pointer == p)
{
if (a->prev)
{
a->prev->next = a->next;
@ -162,13 +177,6 @@ MemoryFree(void *p)
}
free(a);
free(p);
break;
}
a = a->prev;
}
pthread_mutex_unlock(&lock);
}
@ -205,9 +213,7 @@ MemoryFreeAll(void)
{
MemoryInfo *prev = a->prev;
free(a->pointer);
free(a);
a = prev;
}
@ -221,12 +227,18 @@ MemoryInfoGet(void *p)
{
MemoryInfo *a;
pthread_mutex_lock(&lock);
if (!p)
{
return NULL;
}
p = &(((MemoryInfo *) p)[-1]);
a = lastAllocation;
while (a)
{
if (a->pointer == p)
if (a == p)
{
break;
}
@ -278,7 +290,7 @@ MemoryInfoGetPointer(MemoryInfo * a)
return NULL;
}
return a->pointer;
return &(a[1]);
}
void

View file

@ -57,6 +57,9 @@ TelodendriaMemoryHook(MemoryAction a, MemoryInfo * i, void *args)
case MEMORY_FREE:
action = "Freed";
break;
case MEMORY_BAD_POINTER:
Log(lc, LOG_WARNING, "Bad pointer passed into a memory function.");
return;
default:
action = "Unknown operation on";
break;
@ -76,9 +79,9 @@ TelodendriaMemoryIterator(MemoryInfo * i, void *args)
/* We haven't freed the logger memory yet */
if (MemoryInfoGetPointer(i) != lc)
{
Log(lc, LOG_DEBUG, "%lu bytes of memory at %p leaked from %s:%d",
MemoryInfoGetSize(i), MemoryInfoGetPointer(i),
MemoryInfoGetFile(i), MemoryInfoGetLine(i));
Log(lc, LOG_WARNING, "%s:%d: %lu bytes of memory at %p leaked.",
MemoryInfoGetFile(i), MemoryInfoGetLine(i),
MemoryInfoGetSize(i), MemoryInfoGetPointer(i));
}
}
@ -148,6 +151,8 @@ main(int argc, char **argv)
MatrixHttpHandlerArgs matrixArgs;
memset(&matrixArgs, 0, sizeof(matrixArgs));
lc = LogConfigCreate();
if (!lc)

View file

@ -30,7 +30,8 @@ typedef enum MemoryAction
{
MEMORY_ALLOCATE,
MEMORY_REALLOCATE,
MEMORY_FREE
MEMORY_FREE,
MEMORY_BAD_POINTER
} MemoryAction;
#define Malloc(x) MemoryAllocate(x, __FILE__, __LINE__)