From 58374e851737e1bcbc697af9e14d630be66e1f4f Mon Sep 17 00:00:00 2001 From: Syndamia Date: Thu, 30 Apr 2026 09:23:57 +0300 Subject: feat(MemoryManager): Implement M_std_tracked Functions like M_std, but also tracks allocated and freed memory, allowing all allocated memory to be destroyed. --- MemoryManager.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MemoryManager.h | 1 + example.c | 2 +- 3 files changed, 152 insertions(+), 1 deletion(-) diff --git a/MemoryManager.c b/MemoryManager.c index 53f906e..dd3a7fc 100644 --- a/MemoryManager.c +++ b/MemoryManager.c @@ -3,6 +3,8 @@ #include #include +/** M_std **/ + Result std_alloc(MemoryManager mm, void **ptr, usize size) { if (NULL == ptr) @@ -46,6 +48,154 @@ M_std() { }; } +/** M_std_tracked **/ + +struct MemoryTracking { + usize alloc; + void **ptrs; +}; + +static inline Result +MemoryTracking_store(struct MemoryTracking *mt, void *ptr) { + if (NULL == mt || NULL == ptr) + return R_NullArgument; + + if (NULL == mt->ptrs || 0 == mt->alloc) + return R_Uninitialized; + + usize index = 0; + while (index < mt->alloc && NULL != mt->ptrs[index]) { + ++index; + } + + if (index == mt->alloc) { + mt->ptrs = realloc(mt->ptrs, sizeof(void*) * (mt->alloc << 1)); + memset(mt->ptrs + (sizeof(void*) * mt->alloc), 0, sizeof(void*) * mt->alloc); + + if (NULL == mt->ptrs) { + mt->alloc = 0; + return R_OutOfMemory; + } + + mt->alloc <<= 1; + } + + mt->ptrs[index] = ptr; + return R_Ok; +} + +static inline Result +MemoryTracking_remove(struct MemoryTracking *mt, void *ptr) { + if (NULL == mt || NULL == ptr) + return R_NullArgument; + + if (NULL == mt->ptrs || 0 == mt->alloc) + return R_Uninitialized; + + usize index = 0; + while (index < mt->alloc && ptr != mt->ptrs[index]) { + ++index; + } + + if (index == mt->alloc) + return R_NotFound; + + mt->ptrs[index] = NULL; + return R_Ok; +} + +Result +stdt_alloc(MemoryManager mm, void **ptr, usize size) { + if (NULL == ptr) + return R_NullArgument; + + if (NULL == mm.priv) + return R_Uninitialized; + + *ptr = malloc(size); + if (NULL == *ptr) + return R_Err; + + return MemoryTracking_store(mm.priv, *ptr); +} + +Result +stdt_realloc(MemoryManager mm, void **ptr, usize new_size) { + if (NULL == ptr) + return R_NullArgument; + + if (NULL == mm.priv) + return R_Uninitialized; + + void *ptr_orig = *ptr; + *ptr = realloc(*ptr, new_size); + + if (NULL == *ptr) + return R_Err; + + if (ptr_orig != *ptr) { + RETURN_NOTOK(MemoryTracking_remove(mm.priv, ptr_orig)); + RETURN_NOTOK(MemoryTracking_store(mm.priv, *ptr)); + } + return R_Ok; +} + +Result +stdt_free(MemoryManager mm, void **ptr) { + if (NULL == ptr) + return R_NullArgument; + + if (NULL == mm.priv) + return R_Uninitialized; + + RETURN_NOTOK(MemoryTracking_remove(mm.priv, *ptr)); + + free(*ptr); + *ptr = NULL; + + return R_Ok; +} + +Result +stdt_destroy(MemoryManager *mm) { + if (NULL == mm) + return R_NullArgument; + + if (NULL == mm->priv) + return R_Uninitialized; + + struct MemoryTracking *mt = mm->priv; + + for (usize i = 0; i < mt->alloc; ++i) { + if (NULL != mt->ptrs[i]) + free(mt->ptrs[i]); + } + + free(mt->ptrs); + free(mt); + mm->priv = NULL; + + return R_Ok; +} + +MemoryManager +M_std_tracked() { + struct MemoryTracking *mt = malloc(sizeof(struct MemoryTracking)); + mt->alloc = 8; + mt->ptrs = malloc(sizeof(void*) * mt->alloc); + memset(mt->ptrs, 0, sizeof(void*) * mt->alloc); + + return (MemoryManager) { + .alloc = &stdt_alloc, + .realloc = &stdt_realloc, + .free = &stdt_free, + .destroy = &stdt_destroy, + .priv = mt, + }; +} + +/* Helper functions */ + char* M_strdup(MemoryManager mm, const char* str) { if (NULL == str) diff --git a/MemoryManager.h b/MemoryManager.h index 3f1461b..1025e69 100644 --- a/MemoryManager.h +++ b/MemoryManager.h @@ -12,6 +12,7 @@ typedef struct MemoryManager { } MemoryManager; MemoryManager M_std(); +MemoryManager M_std_tracked(); /* Helper functions */ diff --git a/example.c b/example.c index 3808acd..6dc3525 100644 --- a/example.c +++ b/example.c @@ -7,7 +7,7 @@ int main() { - MemoryManager g = M_bump(KiB(2)), + MemoryManager g = M_std_tracked(), t = M_bump(KiB(4)); String *hexes = V_new(&g, sizeof(String), 8); -- cgit v1.2.3