diff --git a/minimal_heap.h b/minimal_heap.h index 71697cb..e995dfb 100644 --- a/minimal_heap.h +++ b/minimal_heap.h @@ -91,6 +91,11 @@ typedef struct _MIHP_HeapMemoryAreaHeader uint32_t Checksum; // Checksum must be the last member ! } MIHP_HeapMemoryAreaHeader; +typedef struct _MIHP_AllocationCustomMetadata +{ + uint8_t data[16]; +} MIHP_AllocationCustomMetadata; + // This structs size must be multiple of 8 typedef struct _MIHP_HeapSegmentHeader { @@ -101,9 +106,9 @@ typedef struct _MIHP_HeapSegmentHeader struct _MIHP_HeapSegmentHeader* PreviousSegment; struct _MIHP_HeapMemoryAreaHeader* OwningMemoryArea; - uint8_t _padding0[16]; + struct _MIHP_AllocationCustomMetadata CustomMetadata; - uint32_t Checksum; // Checksum must be the last member ! + uint32_t Checksum; // Checksum must be the last member ! } MIHP_HeapSegmentHeader; @@ -134,11 +139,18 @@ void* MIHP_Allocate(MIHP_Heap* heap, size_t size); void* MIHP_Reallocate(MIHP_Heap* heap, void* ptr, size_t newSize); bool MIHP_Free(MIHP_Heap* heap, void* ptr); +bool MIHP_SetCustomMetadata(MIHP_Heap* heap, void* ptr, MIHP_AllocationCustomMetadata metadata); +bool MIHP_GetCustomMetadata(MIHP_Heap* heap, void* ptr, MIHP_AllocationCustomMetadata* outMetadata); + bool MIHP_MergeHeaps(MIHP_Heap* sourceHeap, MIHP_Heap* heapToAbsorb); bool MIHP_IsPointerInHeap(MIHP_Heap* heap, void* ptr); size_t MIHP_GetPtrAllocationSize(MIHP_Heap* heap, void* ptr); void MIHP_ValidateHeap(MIHP_Heap* heap); + +typedef void(MIHP_WalkHeapCallbackFn)(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area, const MIHP_HeapSegmentHeader* segment); + +bool MIHP_WalkHeap(MIHP_Heap* heap, MIHP_WalkHeapCallbackFn* callback); /* */ /* Internals */ diff --git a/minimal_heap_implementation.inl b/minimal_heap_implementation.inl index 331ddf8..64fe6f4 100644 --- a/minimal_heap_implementation.inl +++ b/minimal_heap_implementation.inl @@ -82,9 +82,6 @@ bool MIHP_IsHeapInitialized(const MIHP_Heap* heap) bool MIHP_UninitializeHeap(MIHP_Heap* heap, bool force) { - if (heap == NULL) - return false; - if (!MIHP_IsHeapInitialized(heap)) return false; @@ -107,7 +104,7 @@ bool MIHP_UninitializeHeap(MIHP_Heap* heap, bool force) void* MIHP_Allocate(MIHP_Heap* heap, size_t size) { - if (heap == NULL) + if (!MIHP_IsHeapInitialized(heap)) return NULL; if (size == 0) @@ -228,9 +225,6 @@ void* MIHP_Reallocate(MIHP_Heap* heap, void* ptr, size_t newSize) return NULL; } - if (heap == NULL) - return NULL; - if (ptr == NULL) return MIHP_Allocate(heap, newSize); @@ -302,12 +296,6 @@ void* MIHP_Reallocate(MIHP_Heap* heap, void* ptr, size_t newSize) bool MIHP_Free(MIHP_Heap* heap, void* ptr) { - if (heap == NULL) - return false; - - if (ptr == NULL) - return false; - if (!MIHP_IsPointerInHeap(heap, ptr)) return false; @@ -385,14 +373,33 @@ bool MIHP_Free(MIHP_Heap* heap, void* ptr) return true; } +bool MIHP_SetCustomMetadata(MIHP_Heap* heap, void* ptr, MIHP_AllocationCustomMetadata metadata) +{ + if (!MIHP_IsPointerInHeap(heap, ptr)) + return false; + + MIHP_HeapSegmentHeader* segment = MIHP_GetSegmentHeaderPtr(heap, ptr); + MIHP_ValidateHeapSegmentHeader(heap, segment); + segment->CustomMetadata = metadata; + return true; +} + +bool MIHP_GetCustomMetadata(MIHP_Heap* heap, void* ptr, MIHP_AllocationCustomMetadata* outMetadata) +{ + if (outMetadata == NULL) + return false; + + if (!MIHP_IsPointerInHeap(heap, ptr)) + return false; + + MIHP_HeapSegmentHeader* segment = MIHP_GetSegmentHeaderPtr(heap, ptr); + MIHP_ValidateHeapSegmentHeader(heap, segment); + *outMetadata = segment->CustomMetadata; + return true; +} + bool MIHP_MergeHeaps(MIHP_Heap* sourceHeap, MIHP_Heap* heapToAbsorb) { - if (sourceHeap == NULL) - return false; - - if (heapToAbsorb == NULL) - return false; - if (!MIHP_IsHeapInitialized(sourceHeap)) return false; @@ -448,7 +455,7 @@ bool MIHP_MergeHeaps(MIHP_Heap* sourceHeap, MIHP_Heap* heapToAbsorb) bool MIHP_IsPointerInHeap(MIHP_Heap* heap, void* ptr) { - if (heap == NULL) + if (!MIHP_IsHeapInitialized(heap)) return false; MIHP_LockHeap(heap); @@ -492,6 +499,11 @@ size_t MIHP_GetPtrAllocationSize(MIHP_Heap* heap, void* ptr) void MIHP_ValidateHeap(MIHP_Heap* heap) { + if (!MIHP_IsHeapInitialized(heap)) + return false; + + MIHP_LockHeap(heap); + MIHP_HeapMemoryAreaHeader* nextArea = heap->FirstArea; while (nextArea) { @@ -507,6 +519,37 @@ void MIHP_ValidateHeap(MIHP_Heap* heap) nextSegment = currentSegment->NextSegment; } } + + MIHP_UnlockHeap(heap); +} + +bool MIHP_WalkHeap(MIHP_Heap* heap, MIHP_WalkHeapCallbackFn* callback) +{ + if (!MIHP_IsHeapInitialized(heap)) + return false; + + if (callback == NULL) + return false; + + MIHP_HeapMemoryAreaHeader* nextArea = heap->FirstArea; + while (nextArea != NULL) + { + MIHP_HeapMemoryAreaHeader* currentArea = nextArea; + MIHP_ValidateHeapMemoryAreaHeader(heap, currentArea); + nextArea = currentArea->NextArea; + + MIHP_HeapSegmentHeader* nextSegment = currentArea->FirstSegment; + while (nextSegment != NULL) + { + MIHP_HeapSegmentHeader* currentSegment = nextSegment; + MIHP_ValidateHeapSegmentHeader(heap, currentSegment); + nextSegment = currentSegment->NextSegment; + + callback(heap, currentArea, currentSegment); + } + } + + return true; } void MIHP_LockHeap(MIHP_Heap* heap) diff --git a/minimal_heap_test.c b/minimal_heap_test.c index da65fb0..79d4548 100644 --- a/minimal_heap_test.c +++ b/minimal_heap_test.c @@ -5,6 +5,9 @@ #include #include +#include +#include + #define USE_MALLOC 0 #define MIHP_ValidateHeap(x) @@ -30,6 +33,11 @@ void OnHeapCorruptionDetectedCallback(const MIHP_Heap* heap, MIHP_HeapCorruption void* myptrs[NUM_ALLOCATIONS] = { 0 }; +void* GetThisAddress() +{ + return _ReturnAddress(); +} + int main() { MIHP_HeapConfig config = MIHP_MakeDefaultConfigPreset(); @@ -51,7 +59,23 @@ int main() myptrs[i] = malloc(size); #else myptrs[i] = MIHP_Allocate(&myHeap, size); + + MIHP_AllocationCustomMetadata metadata = { 0 }; + void* ptr = GetThisAddress(); + memcpy(&metadata.data, &ptr, sizeof(void*)); + + MIHP_SetCustomMetadata(&myHeap, myptrs[i], metadata); MIHP_ValidateHeap(&myHeap); + + MIHP_AllocationCustomMetadata outMetadata = { 0 }; + MIHP_GetCustomMetadata(&myHeap, myptrs[i], &outMetadata); + void* returnPtr; + + memcpy(&returnPtr, &outMetadata.data, sizeof(void*)); + + MIHP_ASSERT(ptr == returnPtr); + + __debugbreak(); #endif }