diff --git a/minimal_heap.h b/minimal_heap.h index 268a840..d18771e 100644 --- a/minimal_heap.h +++ b/minimal_heap.h @@ -17,7 +17,7 @@ #endif #ifndef MIHP_MEMSET - #define MIHP_MEMSET(Ptr, Size, Val) for(size_t i = 0; i < Size; ++i) *((char*)Ptr + i) = Val; + #define MIHP_MEMSET(Ptr, Size, Val) do { for(size_t i = 0; i < Size; ++i) *((char*)Ptr + i) = Val; } while(0); #endif /* */ @@ -62,7 +62,7 @@ typedef struct _MIHP_HeapConfig void* HeapLock; // Does not need to be reentred safe, can be NULL to disable locking MIHP_LockHeapFn* LockHeapFn; // Can be NULL if HeapLock is NULL - MIHP_LockHeapFn* UnlockHeapFn; // Can be NULL if HeapLock is NULL + MIHP_UnlockHeapFn* UnlockHeapFn; // Can be NULL if HeapLock is NULL } MIHP_HeapConfig; typedef struct _MIHP_HeapStats @@ -73,7 +73,6 @@ typedef struct _MIHP_HeapStats size_t TotalSize; } MIHP_HeapStats; -// This structs size must be multiple of 8 typedef struct _MIHP_HeapMemoryAreaHeader { size_t AreaSize; @@ -86,6 +85,7 @@ typedef struct _MIHP_HeapMemoryAreaHeader struct _MIHP_HeapSegmentHeader* FirstSegment; struct _MIHP_HeapSegmentHeader* LastSuccessfulAllocationSegment; + // TODO: Change this to an InstigatingHeapUuid (opaque ptr) const struct _MIHP_Heap* InstigatingHeap; // Heap that created this area. May not always be the owning heap (in case of a merge) or safe to deference! uint32_t Checksum; // Checksum must be the last member ! @@ -96,7 +96,6 @@ typedef struct _MIHP_AllocationCustomMetadata uint8_t data[16]; } MIHP_AllocationCustomMetadata; -// This structs size must be multiple of 8 typedef struct _MIHP_HeapSegmentHeader { size_t SegmentSize; @@ -109,7 +108,6 @@ typedef struct _MIHP_HeapSegmentHeader struct _MIHP_AllocationCustomMetadata CustomMetadata; uint32_t Checksum; // Checksum must be the last member ! - } MIHP_HeapSegmentHeader; typedef struct _MIHP_HeapCorruptionInfo diff --git a/minimal_heap_implementation.inl b/minimal_heap_implementation.inl index 5a3c802..6903db6 100644 --- a/minimal_heap_implementation.inl +++ b/minimal_heap_implementation.inl @@ -1,5 +1,5 @@ -#define MIHP_MIN(A, B) (A) < (B) ? (A) : (B) -#define MIHP_MAX(A, B) (A) > (B) ? (A) : (B) +#define MIHP_MIN(A, B) ((A) < (B) ? (A) : (B)) +#define MIHP_MAX(A, B) ((A) > (B) ? (A) : (B)) #define MIHP_IS_PO2(Val) (Val != 0 && (Val & (Val - 1)) == 0) @@ -66,6 +66,9 @@ bool MIHP_InitializeHeap(MIHP_Heap* heap, MIHP_HeapConfig config) heap->Config = config; heap->FirstArea = MIHP_CreateHeapMemoryArea(heap, config.MinMemoryAreaSize); + if (heap->FirstArea == NULL) + return false; + heap->LastSuccessfulAllocationArea = heap->FirstArea; heap->FirstArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, heap->FirstArea); @@ -185,7 +188,7 @@ void* MIHP_Allocate(MIHP_Heap* heap, size_t size) /// /// No free segment found (in time), allocate new area /// - + size_t newAreaSize = heap->Stats.TotalSize / 4; // growth-rate of 1.25 while (newAreaSize < size) @@ -309,18 +312,20 @@ bool MIHP_Free(MIHP_Heap* heap, void* ptr) if (segment->OccupiedSize == 0) { - MIHP_HeapCorruptionInfo corruptionInfo = {0}; + MIHP_HeapCorruptionInfo corruptionInfo = { 0 }; corruptionInfo.Type = MIHP_HCE_DoubleFree; corruptionInfo.Ptr = ptr; if (heap->Config.OnHeapCorruptionDetectedFn != NULL) heap->Config.OnHeapCorruptionDetectedFn(heap, corruptionInfo); + + MIHP_UnlockHeap(heap); return false; } segment->OccupiedSize = 0; segment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, segment); - + area->NumOccupiedSegments--; area->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, area); @@ -468,7 +473,7 @@ bool MIHP_IsPointerInHeap(MIHP_Heap* heap, void* ptr) MIHP_HeapMemoryAreaHeader* currentArea = nextArea; MIHP_ValidateHeapMemoryAreaHeader(heap, currentArea); nextArea = currentArea->NextArea; - + uintptr_t ptrMin = (uintptr_t)currentArea; uintptr_t ptrMax = (uintptr_t)currentArea + currentArea->AreaSize; @@ -494,6 +499,7 @@ size_t MIHP_GetPtrAllocationSize(MIHP_Heap* heap, void* ptr) MIHP_HeapSegmentHeader* segment = (MIHP_HeapSegmentHeader*)((char*)ptr - segmentHeaderSize); MIHP_ValidateHeapSegmentHeader(heap, segment); + MIHP_UnlockHeap(heap); return segment->OccupiedSize; } @@ -672,7 +678,7 @@ bool MIHP_SplitHeapSegment(MIHP_Heap* heap, MIHP_HeapSegmentHeader* sourceSegmen if (sourceResultingSegmentSize < MIHP_GetMinimalPayloadSize(heap) + headerSize) return false; - + if (sourceResultingSegmentSize < sourceSegment->OccupiedSize + headerSize) return false; diff --git a/minimal_heap_test.c b/minimal_heap_test.c index 79d4548..8a0f00f 100644 --- a/minimal_heap_test.c +++ b/minimal_heap_test.c @@ -74,8 +74,6 @@ int main() memcpy(&returnPtr, &outMetadata.data, sizeof(void*)); MIHP_ASSERT(ptr == returnPtr); - - __debugbreak(); #endif }