From 957c64c7b8b5e98d8a03dd84c7e27e7991fb9dbc Mon Sep 17 00:00:00 2001 From: iamcheeseman Date: Mon, 6 Apr 2026 17:04:05 -0400 Subject: Initial commit --- common/mem.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 common/mem.c (limited to 'common/mem.c') diff --git a/common/mem.c b/common/mem.c new file mode 100644 index 0000000..4196812 --- /dev/null +++ b/common/mem.c @@ -0,0 +1,200 @@ +#include "mem.h" + +#include + +#include "common.h" +#include "dyn_arr.h" + +// Array to track temp allocations. +void **temp_allocations; + +#ifdef UE_DEBUG + +#include + +#define BACKTRACE_SIZE 16 + +struct alloc { + void *ptr; + size_t size; + int backtrace_len; + char **backtrace; +}; + +int allocations_cap; +int allocations_len; +struct alloc *allocations; + +#endif // UE_DEBUG + +static +void *glfw_alloc(size_t size, void *user) +{ + (void)user; + return mem_alloc(size); +} + +static +void *glfw_realloc(void *block, size_t size, void *user) +{ + (void)user; + return mem_realloc(block, size); +} + +static +void glfw_dealloc(void *block, void *user) +{ + (void)user; + mem_free(block); +} + +void init_mem(void) +{ +#ifdef UE_DEBUG + allocations_len = 0; + allocations_cap = 8; + allocations = malloc(sizeof(struct alloc) * 8); + if (!allocations) + log_fatal(ERR_MEM, "(%s) (track) ran out of memory", __func__); +#endif // UE_DEBUG + + GLFWallocator glfw_allocator; + glfw_allocator.allocate = glfw_alloc; + glfw_allocator.reallocate = glfw_realloc; + glfw_allocator.deallocate = glfw_dealloc; + glfwInitAllocator(&glfw_allocator); + + temp_allocations = da_create(void*, 0); +} + +void deinit_mem(void) +{ + da_free(temp_allocations); +#ifdef UE_DEBUG + fprintf(stderr, "%d allocations leaked\n", allocations_len); + for (int i = 0; i < allocations_len; i++) { + struct alloc *alloc = &allocations[i]; + fprintf( + stderr, + "leaked %zu bytes at %p\n", + alloc->size, + alloc->ptr + ); + for (int j = 0; j < alloc->backtrace_len; j++) { + fprintf(stderr, "\t%s\n", alloc->backtrace[j]); + } + putc('\n', stderr); + + free(alloc->backtrace); + } + free(allocations); + + if (allocations_len > 0) + exit(ERR_MEM_LEAK); +#endif // UE_DEBUG +} + +void free_temp_allocs(void) +{ + for (int i = 0; i < da_len(temp_allocations); i++) { + void *temp = temp_allocations[i]; + mem_free(temp); + } + da_clear(temp_allocations); +} + +void *mem_alloc(size_t size) +{ + void *ptr = malloc(size); + if (!ptr) + log_fatal(ERR_MEM, "(%s) ran out of memory", __func__); + +#ifdef UE_DEBUG + // Log allocation + struct alloc alloc; + void *bt[BACKTRACE_SIZE]; + int bt_len = backtrace(bt, BACKTRACE_SIZE); + char **symbols = backtrace_symbols(bt, bt_len); + + alloc.ptr = ptr; + alloc.size = size; + alloc.backtrace_len = bt_len; + alloc.backtrace = symbols; + + if (allocations_len + 1 > allocations_cap) { + allocations_cap *= 2; + allocations = realloc( + allocations, + sizeof(struct alloc) * allocations_cap + ); + if (!allocations) + log_fatal( + ERR_MEM, + "(%s) (track) ran out of memory", + __func__ + ); + } + + allocations[allocations_len++] = alloc; +#endif // UE_DEBUG + + return ptr; +} + +void *mem_realloc(void *ptr, size_t new_size) +{ + if (new_size == 0) { + mem_free(ptr); + return NULL; + } + + void *new_ptr = realloc(ptr, new_size); + if (!new_ptr) + log_fatal(ERR_MEM, "(%s) ran out of memory", __func__); + +#ifdef UE_DEBUG + for (int i = 0; i < allocations_len; i++) { + struct alloc *alloc = &allocations[i]; + if (alloc->ptr == ptr) { + alloc->ptr = new_ptr; + alloc->size = new_size; + break; + } + } +#endif // UE_DEBUG + + return new_ptr; +} + +void *mem_talloc(size_t size) +{ + void *ptr = mem_alloc(size); + da_append(void*, &temp_allocations, ptr); + return ptr; +} + +void mem_free(void *ptr) +{ + free(ptr); + +#ifdef UE_DEBUG + for (int i = 0; i < allocations_len; i++) { + struct alloc *alloc = &allocations[i]; + if (alloc->ptr == ptr) { + free(alloc->backtrace); + *alloc = allocations[allocations_len - 1]; + allocations_len--; + break; + } + } +#endif // UE_DEBUG +} + +int alloc_count(void) +{ +#ifdef UE_DEBUG + return allocations_len; +#else + return -1; +#endif +} -- cgit v1.3-2-g0d8e