From 174be6a022a7584d4cb3b057c26f281c628e24c7 Mon Sep 17 00:00:00 2001 From: ToyB-Chan Date: Mon, 8 Jun 2026 19:20:58 +0200 Subject: [PATCH] fixed when compacting segment on realloc, the new segment not getting merged with the following empty segment --- minimal_heap.h | 41 ++++++++++++++++----------------- minimal_heap_implementation.inl | 40 +++++++++++++++++--------------- minimal_heap_test.c | 2 +- 3 files changed, 43 insertions(+), 40 deletions(-) diff --git a/minimal_heap.h b/minimal_heap.h index 967087e..f341c7d 100644 --- a/minimal_heap.h +++ b/minimal_heap.h @@ -1,5 +1,7 @@ +/* Version 1.2 */ -/* Version 1.1 */ +#ifndef __MINIMAL_HEAP_H__ +#define __MINIMAL_HEAP_H__ #include #include @@ -13,9 +15,6 @@ #define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER 1 #define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM 2 -#ifndef __MINIMAL_HEAP_H__ -#define __MINIMAL_HEAP_H__ - /* Defines to be configured by the library user */ #ifndef MIHP_HEAP_STRUCTURE_VALIDATION_TYPE #define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM @@ -72,7 +71,7 @@ typedef struct _MIHP_HeapMemoryAreaHeader struct _MIHP_HeapMemoryAreaHeader* NextArea; struct _MIHP_HeapMemoryAreaHeader* PreviousArea; - struct _MIHP_HeapInfo* OwningHeap; + struct _MIHP_Heap* OwningHeap; struct _MIHP_HeapSegmentHeader* FirstSegment; @@ -97,14 +96,14 @@ typedef struct _MIHP_HeapSegmentHeader typedef struct _MIHP_HeapCorruptionInfo { - const struct _MIHP_HeapInfo* Heap; + const struct _MIHP_Heap* Heap; uint8_t Type; const void* Ptr; uint32_t ExpectedValue; uint32_t ActualValue; } MIHP_HeapCorruptionInfo; -typedef struct _MIHP_HeapInfo +typedef struct _MIHP_Heap { MIHP_HeapConfig Config; MIHP_HeapStats Stats; @@ -112,23 +111,23 @@ typedef struct _MIHP_HeapInfo MIHP_HeapMemoryAreaHeader* LastSuccessfulAllocationArea; MIHP_HEAP_LOCK_TYPE HeapLock; -} MIHP_HeapInfo; +} MIHP_Heap; /* API Interface */ -MIHP_HeapInfo* MIHP_CreateHeap(MIHP_HeapConfig config); -bool MIHP_DestroyHeap(MIHP_HeapInfo* heap, bool force); -void* MIHP_Allocate(MIHP_HeapInfo* heap, size_t size); -void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize); -bool MIHP_Free(MIHP_HeapInfo* heap, void* ptr); +MIHP_Heap* MIHP_CreateHeap(MIHP_HeapConfig config); +bool MIHP_DestroyHeap(MIHP_Heap* heap, bool force); +void* MIHP_Allocate(MIHP_Heap* heap, size_t size); +void* MIHP_Realloc(MIHP_Heap* heap, void* ptr, size_t newSize); +bool MIHP_Free(MIHP_Heap* heap, void* ptr); -bool MIHP_IsPointerInHeap(MIHP_HeapInfo* heap, void* ptr); -size_t MIHP_GetPtrAllocationSize(MIHP_HeapInfo* heap, void* ptr); -void MIHP_ValidateHeap(MIHP_HeapInfo* heap); +bool MIHP_IsPointerInHeap(MIHP_Heap* heap, void* ptr); +size_t MIHP_GetPtrAllocationSize(MIHP_Heap* heap, void* ptr); +void MIHP_ValidateHeap(MIHP_Heap* heap); /* */ /* Internals */ -MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_HeapInfo* heap, size_t requestedSize); -bool MIHP_DestroyHeapMemoryArea(MIHP_HeapInfo* heap, MIHP_HeapMemoryAreaHeader* area); +MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_Heap* heap, size_t requestedSize); +bool MIHP_DestroyHeapMemoryArea(MIHP_Heap* heap, MIHP_HeapMemoryAreaHeader* area); MIHP_HeapSegmentHeader* MIHP_InitializeHeapSegment(MIHP_HeapMemoryAreaHeader* area, void* segmentStart, size_t size); bool MIHP_UninitializeHeapSegment(MIHP_HeapSegmentHeader* segment); @@ -136,14 +135,14 @@ bool MIHP_UninitializeHeapSegment(MIHP_HeapSegmentHeader* segment); bool MIHP_SplitHeapSegment(MIHP_HeapSegmentHeader* sourceSegment, size_t newSegmentSize, MIHP_HeapSegmentHeader** outNewSegment); bool MIHP_MergeHeapSegments(MIHP_HeapSegmentHeader* sourceSegment, MIHP_HeapSegmentHeader* segmentToAbsorb); -size_t MIHP_GetHeapAlignedSize(const MIHP_HeapInfo* heap, size_t size); +size_t MIHP_GetHeapAlignedSize(const MIHP_Heap* heap, size_t size); uint32_t MIHP_HashMemoryRegion(const void* data, size_t size); uint32_t MIHP_GenerateHeapMemoryAreaChecksum(const MIHP_HeapMemoryAreaHeader* area); uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_HeapSegmentHeader* segment); -void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapInfo* heap, const MIHP_HeapMemoryAreaHeader* area); -void MIHP_ValidateHeapSegmentHeader(const MIHP_HeapInfo* heap, const MIHP_HeapSegmentHeader* segment); +void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area); +void MIHP_ValidateHeapSegmentHeader(const MIHP_Heap* heap, const MIHP_HeapSegmentHeader* segment); /* */ #endif diff --git a/minimal_heap_implementation.inl b/minimal_heap_implementation.inl index c87848d..3db0db5 100644 --- a/minimal_heap_implementation.inl +++ b/minimal_heap_implementation.inl @@ -5,7 +5,7 @@ #define MIHP_IS_PO2(Val) (Val != 0 && (Val & (Val - 1)) == 0) -MIHP_HeapInfo* MIHP_CreateHeap(MIHP_HeapConfig config) +MIHP_Heap* MIHP_CreateHeap(MIHP_HeapConfig config) { if (config.AllocationAlignment < sizeof(size_t)) return NULL; @@ -13,11 +13,11 @@ MIHP_HeapInfo* MIHP_CreateHeap(MIHP_HeapConfig config) if (!MIHP_IS_PO2(config.AllocationAlignment)) return NULL; - MIHP_HeapInfo* heap = (MIHP_HeapInfo*)MIHP_PlatformRequestMemory(sizeof(MIHP_HeapInfo)); + MIHP_Heap* heap = (MIHP_Heap*)MIHP_PlatformRequestMemory(sizeof(MIHP_Heap)); if (heap == NULL) return NULL; - MIHP_MEMSET(heap, sizeof(MIHP_HeapInfo), 0); + MIHP_MEMSET(heap, sizeof(MIHP_Heap), 0); heap->Config = config; @@ -25,7 +25,7 @@ MIHP_HeapInfo* MIHP_CreateHeap(MIHP_HeapConfig config) heap->LastSuccessfulAllocationArea = heap->FirstArea; if (heap->FirstArea == NULL) { - MIHP_PlatformFreeMemory(heap, sizeof(MIHP_HeapInfo)); + MIHP_PlatformFreeMemory(heap, sizeof(MIHP_Heap)); return NULL; } @@ -34,7 +34,7 @@ MIHP_HeapInfo* MIHP_CreateHeap(MIHP_HeapConfig config) return heap; } -bool MIHP_DestroyHeap(MIHP_HeapInfo* heap, bool force) +bool MIHP_DestroyHeap(MIHP_Heap* heap, bool force) { if (heap == NULL) return false; @@ -52,11 +52,11 @@ bool MIHP_DestroyHeap(MIHP_HeapInfo* heap, bool force) MIHP_DestroyHeapMemoryArea(heap, currentArea); } - MIHP_PlatformFreeMemory(heap, sizeof(MIHP_HeapInfo)); + MIHP_PlatformFreeMemory(heap, sizeof(MIHP_Heap)); return true; } -void* MIHP_Allocate(MIHP_HeapInfo* heap, size_t size) +void* MIHP_Allocate(MIHP_Heap* heap, size_t size) { if (heap == NULL) return NULL; @@ -152,7 +152,7 @@ void* MIHP_Allocate(MIHP_HeapInfo* heap, size_t size) return MIHP_Allocate(heap, size); } -void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize) +void* MIHP_Realloc(MIHP_Heap* heap, void* ptr, size_t newSize) { if (newSize == 0) { @@ -216,7 +216,11 @@ void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize) if (segment->SegmentSize > 2 * segmentHeaderSize + alignedNewSize + minimumPayloadSize) { size_t newSplitSegmentSize = segment->SegmentSize - segmentHeaderSize - alignedNewSize; - MIHP_SplitHeapSegment(segment, newSplitSegmentSize, NULL); + + MIHP_HeapSegmentHeader* newSpittedSegment = NULL; + MIHP_SplitHeapSegment(segment, newSplitSegmentSize, &newSpittedSegment); + if (newSpittedSegment && newSpittedSegment->NextSegment) + MIHP_MergeHeapSegments(newSpittedSegment, newSpittedSegment->NextSegment); } MIHP_UNLOCK_HEAP(&heap->HeapLock); @@ -227,7 +231,7 @@ void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize) return ptr; } -bool MIHP_Free(MIHP_HeapInfo* heap, void* ptr) +bool MIHP_Free(MIHP_Heap* heap, void* ptr) { if (heap == NULL) return false; @@ -304,7 +308,7 @@ bool MIHP_Free(MIHP_HeapInfo* heap, void* ptr) return true; } -bool MIHP_IsPointerInHeap(MIHP_HeapInfo* heap, void* ptr) +bool MIHP_IsPointerInHeap(MIHP_Heap* heap, void* ptr) { if (heap == NULL) return false; @@ -333,7 +337,7 @@ bool MIHP_IsPointerInHeap(MIHP_HeapInfo* heap, void* ptr) return false; } -size_t MIHP_GetPtrAllocationSize(MIHP_HeapInfo* heap, void* ptr) +size_t MIHP_GetPtrAllocationSize(MIHP_Heap* heap, void* ptr) { if (!MIHP_IsPointerInHeap(heap, ptr)) return 0; @@ -347,7 +351,7 @@ size_t MIHP_GetPtrAllocationSize(MIHP_HeapInfo* heap, void* ptr) return segment->OccupiedSize; } -void MIHP_ValidateHeap(MIHP_HeapInfo* heap) +void MIHP_ValidateHeap(MIHP_Heap* heap) { MIHP_HeapMemoryAreaHeader* nextArea = heap->FirstArea; while (nextArea) @@ -366,7 +370,7 @@ void MIHP_ValidateHeap(MIHP_HeapInfo* heap) } } -MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_HeapInfo* heap, size_t requestedSize) +MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_Heap* heap, size_t requestedSize) { MIHP_ASSERT(heap); @@ -394,7 +398,7 @@ MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_HeapInfo* heap, size_t return area; } -bool MIHP_DestroyHeapMemoryArea(MIHP_HeapInfo* heap, MIHP_HeapMemoryAreaHeader* memoryArea) +bool MIHP_DestroyHeapMemoryArea(MIHP_Heap* heap, MIHP_HeapMemoryAreaHeader* memoryArea) { MIHP_ASSERT(heap); MIHP_ASSERT(memoryArea); @@ -516,7 +520,7 @@ bool MIHP_MergeHeapSegments(MIHP_HeapSegmentHeader* sourceSegment, MIHP_HeapSegm return true; } -size_t MIHP_GetHeapAlignedSize(const MIHP_HeapInfo* heap, size_t size) +size_t MIHP_GetHeapAlignedSize(const MIHP_Heap* heap, size_t size) { return (size + (heap->Config.AllocationAlignment - 1)) & ~(heap->Config.AllocationAlignment - 1); } @@ -573,7 +577,7 @@ uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_HeapSegmentHeader* segment) #endif } -void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapInfo* heap, const MIHP_HeapMemoryAreaHeader* area) +void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area) { uint32_t newChecksum; @@ -600,7 +604,7 @@ void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapInfo* heap, const MIHP_Hea } } -void MIHP_ValidateHeapSegmentHeader(const MIHP_HeapInfo* heap, const MIHP_HeapSegmentHeader* segment) +void MIHP_ValidateHeapSegmentHeader(const MIHP_Heap* heap, const MIHP_HeapSegmentHeader* segment) { uint32_t newChecksum; diff --git a/minimal_heap_test.c b/minimal_heap_test.c index 62e0d38..4c194d0 100644 --- a/minimal_heap_test.c +++ b/minimal_heap_test.c @@ -36,7 +36,7 @@ int main() config.AllocationAlignment = 16; config.MinimalMemoryAreaSize = 4096 * 32; config.MaximalMemoryAreaSize = 4096ull * 4096ull * 4096ull; - MIHP_HeapInfo* myHeap = MIHP_CreateHeap(config); + MIHP_Heap* myHeap = MIHP_CreateHeap(config); for (int i = 0; i < NUM_ALLOCATIONS; i++) {