From a95b064d6d0a2e3dfa8c414be60ae966a099adfd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 21 Apr 2023 13:29:38 +0100 Subject: Fix memory leak caused by awful realloc usage on Linux --- src/common_memory.cpp | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'src/common_memory.cpp') diff --git a/src/common_memory.cpp b/src/common_memory.cpp index f33fb0dff..d6a87529f 100644 --- a/src/common_memory.cpp +++ b/src/common_memory.cpp @@ -1,3 +1,4 @@ +#include gb_internal gb_inline void zero_size(void *ptr, isize len) { memset(ptr, 0, len); @@ -121,7 +122,6 @@ struct PlatformMemoryBlock { PlatformMemoryBlock *prev, *next; }; - gb_global std::atomic global_platform_memory_total_usage; gb_global PlatformMemoryBlock global_platform_memory_block_sentinel; @@ -177,12 +177,12 @@ gb_internal void platform_virtual_memory_protect(void *memory, isize size); gb_printf_err("Total Usage: %lld bytes\n", cast(long long)global_platform_memory_total_usage); GB_ASSERT_MSG(pmblock != nullptr, "Out of Virtual Memory, oh no..."); } - global_platform_memory_total_usage += total_size; + global_platform_memory_total_usage.fetch_add(total_size); return pmblock; } gb_internal void platform_virtual_memory_free(PlatformMemoryBlock *block) { isize size = block->total_size; - global_platform_memory_total_usage -= size; + global_platform_memory_total_usage.fetch_sub(size); munmap(block, size); } gb_internal void platform_virtual_memory_protect(void *memory, isize size) { @@ -396,6 +396,8 @@ gb_internal gbAllocator heap_allocator(void) { return a; } +gb_internal std::atomic total_heap_memory_allocated; + gb_internal GB_ALLOCATOR_PROC(heap_allocator_proc) { void *ptr = nullptr; @@ -403,7 +405,6 @@ gb_internal GB_ALLOCATOR_PROC(heap_allocator_proc) { gb_unused(old_size); - // TODO(bill): Throughly test! switch (type) { #if defined(GB_COMPILER_MSVC) @@ -436,28 +437,34 @@ gb_internal GB_ALLOCATOR_PROC(heap_allocator_proc) { #elif defined(GB_SYSTEM_LINUX) // TODO(bill): *nix version that's decent case gbAllocation_Alloc: { - ptr = aligned_alloc(alignment, (size + alignment - 1) & ~(alignment - 1)); + isize total_size = (size + alignment - 1) & ~(alignment - 1); + total_heap_memory_allocated.fetch_add(total_size); + ptr = aligned_alloc(alignment, total_size); gb_zero_size(ptr, size); } break; case gbAllocation_Free: if (old_memory != nullptr) { + total_heap_memory_allocated.fetch_sub(malloc_usable_size(old_memory)); free(old_memory); } break; - case gbAllocation_Resize: + case gbAllocation_Resize: { if (size == 0) { if (old_memory != nullptr) { + total_heap_memory_allocated.fetch_sub(malloc_usable_size(old_memory)); free(old_memory); } break; } - + alignment = gb_max(alignment, gb_align_of(max_align_t)); - + if (old_memory == nullptr) { - ptr = aligned_alloc(alignment, (size + alignment - 1) & ~(alignment - 1)); + isize total_size = (size + alignment - 1) & ~(alignment - 1); + total_heap_memory_allocated.fetch_add(total_size); + ptr = aligned_alloc(alignment, total_size); gb_zero_size(ptr, size); break; } @@ -466,11 +473,19 @@ gb_internal GB_ALLOCATOR_PROC(heap_allocator_proc) { break; } - ptr = aligned_alloc(alignment, (size + alignment - 1) & ~(alignment - 1)); + size_t actual_old_size = malloc_usable_size(old_memory); + if (size <= actual_old_size) { + ptr = old_memory; + break; + } + + isize total_size = (size + alignment - 1) & ~(alignment - 1); + total_heap_memory_allocated.fetch_add(total_size); + ptr = aligned_alloc(alignment, total_size); gb_memmove(ptr, old_memory, old_size); free(old_memory); gb_zero_size(cast(u8 *)ptr + old_size, gb_max(size-old_size, 0)); - break; + } break; #else // TODO(bill): *nix version that's decent case gbAllocation_Alloc: { -- cgit v1.2.3