aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSyndamia <kamen@syndamia.com>2026-04-30 09:23:57 +0300
committerSyndamia <kamen@syndamia.com>2026-05-12 07:08:56 +0300
commit58374e851737e1bcbc697af9e14d630be66e1f4f (patch)
tree03ead2a220ffdb318bf3036d4edb68a3e576bf97
parent8636d3558523fe30a2be84549c2b6eb5e125e97c (diff)
downloadfoollib-58374e851737e1bcbc697af9e14d630be66e1f4f.tar
foollib-58374e851737e1bcbc697af9e14d630be66e1f4f.tar.gz
foollib-58374e851737e1bcbc697af9e14d630be66e1f4f.zip
feat(MemoryManager): Implement M_std_tracked
Functions like M_std, but also tracks allocated and freed memory, allowing all allocated memory to be destroyed.
-rw-r--r--MemoryManager.c150
-rw-r--r--MemoryManager.h1
-rw-r--r--example.c2
3 files changed, 152 insertions, 1 deletions
diff --git a/MemoryManager.c b/MemoryManager.c
index 53f906e..dd3a7fc 100644
--- a/MemoryManager.c
+++ b/MemoryManager.c
@@ -3,6 +3,8 @@
#include <stdlib.h>
#include <string.h>
+/** 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);