mirror of
https://github.com/ToyB-Chan/minimal-heap.git
synced 2026-11-09 07:02:06 +01:00
Compare commits
11 Commits
error-resu
...
77630e2c47
| Author | SHA1 | Date | |
|---|---|---|---|
| 77630e2c47 | |||
| 2289ec8644 | |||
| 088a3648dd | |||
| a78ec329b4 | |||
| 394e42aae8 | |||
| 9f42297bf2 | |||
| 92eb9456bc | |||
| 947ea6698d | |||
| 164493cdac | |||
| cda05cd84b | |||
| d000447369 |
@@ -2,7 +2,7 @@
|
|||||||
#define __MINIMAL_HEAP_H__
|
#define __MINIMAL_HEAP_H__
|
||||||
|
|
||||||
#define MIHP_VERSION_MAJOR 1
|
#define MIHP_VERSION_MAJOR 1
|
||||||
#define MIHP_VERSION_MINOR 10
|
#define MIHP_VERSION_MINOR 12
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -18,14 +18,14 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MIHP_MEMSET
|
#ifndef MIHP_MEMSET
|
||||||
#define MIHP_MEMSET(Ptr, Size, Val) do { for(size_t i = 0; i < Size; ++i) *((char*)Ptr + i) = Val; } while(0);
|
#define MIHP_MEMSET(Ptr, Val, Size) do { for(size_t i = 0; i < Size; ++i) *((char*)Ptr + i) = Val; } while(0);
|
||||||
#endif
|
#endif
|
||||||
/* */
|
/* */
|
||||||
|
|
||||||
typedef uintptr_t MIHP_HeapOpaque;
|
typedef uintptr_t MIHP_HeapOpaque;
|
||||||
|
|
||||||
typedef void*(MIHP_PlatformRequestMemoryFn)(MIHP_HeapOpaque heap, size_t minRequestedSize, size_t* outActualSize);
|
typedef void*(MIHP_PlatformRequestMemoryFn)(MIHP_HeapOpaque heap, size_t minRequestedSize, size_t* outActualSize);
|
||||||
typedef bool (MIHP_PlatformFreeMemoryFn)(MIHP_HeapOpaque heap, void* Ptr, size_t actualSize);
|
typedef bool (MIHP_PlatformFreeMemoryFn)(MIHP_HeapOpaque heap, void* ptr, size_t actualSize);
|
||||||
|
|
||||||
typedef enum _MIHP_HeapCorruptionError
|
typedef enum _MIHP_HeapCorruptionError
|
||||||
{
|
{
|
||||||
@@ -34,6 +34,9 @@ typedef enum _MIHP_HeapCorruptionError
|
|||||||
MIHP_HCE_DoubleFree = 2
|
MIHP_HCE_DoubleFree = 2
|
||||||
} MIHP_HeapCorruptionError;
|
} MIHP_HeapCorruptionError;
|
||||||
|
|
||||||
|
struct _MIHP_Heap;
|
||||||
|
struct _MIHP_HeapCorruptionInfo;
|
||||||
|
|
||||||
typedef void (MIHP_OnHeapCorruptionDetectedFn)(const struct _MIHP_Heap* heap, struct _MIHP_HeapCorruptionInfo corruptionInfo);
|
typedef void (MIHP_OnHeapCorruptionDetectedFn)(const struct _MIHP_Heap* heap, struct _MIHP_HeapCorruptionInfo corruptionInfo);
|
||||||
|
|
||||||
typedef void(MIHP_LockHeapFn)(MIHP_HeapOpaque heap, void* heapLock);
|
typedef void(MIHP_LockHeapFn)(MIHP_HeapOpaque heap, void* heapLock);
|
||||||
@@ -76,7 +79,9 @@ typedef struct _MIHP_HeapConfig
|
|||||||
uint8_t MinHeapTraversalPercentToExpand; // Minimal integer percent of the heap traversed before expanding the heap
|
uint8_t MinHeapTraversalPercentToExpand; // Minimal integer percent of the heap traversed before expanding the heap
|
||||||
|
|
||||||
size_t AllocationAlignment; // Must be power of two and at least sizeof(size_t)
|
size_t AllocationAlignment; // Must be power of two and at least sizeof(size_t)
|
||||||
uint8_t AllocationInitialValue; // Initial value the returned blocks are to be filled with
|
|
||||||
|
uint8_t AllocateFillValue; // Initial value the returned blocks are to be filled with
|
||||||
|
uint8_t FreeFillValue; // Value freed blocks are to be filled with
|
||||||
|
|
||||||
MIHP_HeapValidationMode HeapValidationMode;
|
MIHP_HeapValidationMode HeapValidationMode;
|
||||||
|
|
||||||
@@ -116,10 +121,10 @@ typedef struct _MIHP_AllocationCustomMetadata
|
|||||||
union
|
union
|
||||||
{
|
{
|
||||||
uint8_t AsU8 [sizeof(size_t) * 2];
|
uint8_t AsU8 [sizeof(size_t) * 2];
|
||||||
uint16_t AsU16 [sizeof(size_t) * 1];
|
uint16_t AsU16 [(sizeof(size_t) * 2) / sizeof(uint16_t)];
|
||||||
uint32_t AsU32 [sizeof(size_t) / 2];
|
uint32_t AsU32 [(sizeof(size_t) * 2) / sizeof(uint32_t)];
|
||||||
void* AsPtr [sizeof(size_t) / 2];
|
void* AsPtr [(sizeof(size_t) * 2) / sizeof(void*)];
|
||||||
uint64_t AsU64 [sizeof(size_t) / 4];
|
uint64_t AsU64 [(sizeof(size_t) * 2) / sizeof(uint64_t)];
|
||||||
};
|
};
|
||||||
} MIHP_AllocationCustomMetadata;
|
} MIHP_AllocationCustomMetadata;
|
||||||
|
|
||||||
@@ -208,7 +213,7 @@ size_t MIHP_GetMinimalPayloadSize(const MIHP_Heap* heap);
|
|||||||
size_t MIHP_GetMaximalPayloadSize(const MIHP_Heap* heap);
|
size_t MIHP_GetMaximalPayloadSize(const MIHP_Heap* heap);
|
||||||
/* */
|
/* */
|
||||||
|
|
||||||
#if MIHP_IMPLEMENTATION
|
#ifdef MIHP_IMPLEMENTATION
|
||||||
#include "minimal_heap_implementation.inl"
|
#include "minimal_heap_implementation.inl"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#include "minimal_heap.h"
|
|
||||||
#define MIHP_MIN(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_MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
|
|
||||||
@@ -22,7 +21,8 @@ MIHP_HeapConfig MIHP_MakeDefaultConfigPreset()
|
|||||||
cfg.MinHeapTraversalPercentToExpand = 80;
|
cfg.MinHeapTraversalPercentToExpand = 80;
|
||||||
|
|
||||||
cfg.AllocationAlignment = 16;
|
cfg.AllocationAlignment = 16;
|
||||||
cfg.AllocationInitialValue = 0xbe;
|
cfg.AllocateFillValue = 0xbe;
|
||||||
|
cfg.FreeFillValue = 0xee;
|
||||||
|
|
||||||
cfg.HeapValidationMode = MIHP_HVM_MagicNumber;
|
cfg.HeapValidationMode = MIHP_HVM_MagicNumber;
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ MIHP_HeapError MIHP_InitializeHeap(MIHP_Heap* heap, MIHP_HeapConfig config)
|
|||||||
return MIHP_HE_BadConfig;
|
return MIHP_HE_BadConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
MIHP_MEMSET(heap, sizeof(MIHP_Heap), 0);
|
MIHP_MEMSET(heap, 0, sizeof(MIHP_Heap));
|
||||||
|
|
||||||
heap->Config = config;
|
heap->Config = config;
|
||||||
heap->FirstArea = MIHP_CreateHeapMemoryArea(heap, config.MinMemoryAreaSize);
|
heap->FirstArea = MIHP_CreateHeapMemoryArea(heap, config.MinMemoryAreaSize);
|
||||||
@@ -112,7 +112,7 @@ MIHP_HeapError MIHP_UninitializeHeap(MIHP_Heap* heap, bool force)
|
|||||||
MIHP_DestroyHeapMemoryArea(heap, currentArea);
|
MIHP_DestroyHeapMemoryArea(heap, currentArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
MIHP_MEMSET(heap, sizeof(MIHP_Heap), 0);
|
MIHP_MEMSET(heap, 0, sizeof(MIHP_Heap));
|
||||||
return MIHP_HE_Success;
|
return MIHP_HE_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ MIHP_HeapResult MIHP_Allocate(MIHP_Heap* heap, size_t size)
|
|||||||
MIHP_UnlockHeap(heap);
|
MIHP_UnlockHeap(heap);
|
||||||
|
|
||||||
void* data = MIHP_GetHeapSegmentPayloadPtr(heap, targetSegment);
|
void* data = MIHP_GetHeapSegmentPayloadPtr(heap, targetSegment);
|
||||||
MIHP_MEMSET(data, size, heap->Config.AllocationInitialValue);
|
MIHP_MEMSET(data, heap->Config.AllocateFillValue, size);
|
||||||
|
|
||||||
return MIHP_MAKE_RESULT(data, MIHP_HE_Success);
|
return MIHP_MAKE_RESULT(data, MIHP_HE_Success);
|
||||||
} while (nextSegment != currentArea->LastSuccessfulAllocationSegment);
|
} while (nextSegment != currentArea->LastSuccessfulAllocationSegment);
|
||||||
@@ -255,7 +255,7 @@ MIHP_HeapResult MIHP_Reallocate(MIHP_Heap* heap, void* ptr, size_t newSize)
|
|||||||
size_t maxPayloadSize = segment->SegmentSize - segmentHeaderSize;
|
size_t maxPayloadSize = segment->SegmentSize - segmentHeaderSize;
|
||||||
if (newSize <= maxPayloadSize)
|
if (newSize <= maxPayloadSize)
|
||||||
{
|
{
|
||||||
MIHP_MEMSET((char*)ptr + segment->OccupiedSize, newSize - segment->OccupiedSize, heap->Config.AllocationInitialValue);
|
MIHP_MEMSET((char*)ptr + segment->OccupiedSize, heap->Config.AllocateFillValue, newSize - segment->OccupiedSize);
|
||||||
segment->OccupiedSize = newSize;
|
segment->OccupiedSize = newSize;
|
||||||
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, segment);
|
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, segment);
|
||||||
|
|
||||||
@@ -289,6 +289,8 @@ MIHP_HeapResult MIHP_Reallocate(MIHP_Heap* heap, void* ptr, size_t newSize)
|
|||||||
}
|
}
|
||||||
else if (newSize < segment->OccupiedSize)
|
else if (newSize < segment->OccupiedSize)
|
||||||
{
|
{
|
||||||
|
MIHP_MEMSET((char*)ptr + newSize, heap->Config.FreeFillValue, segment->OccupiedSize - newSize);
|
||||||
|
|
||||||
segment->OccupiedSize = newSize;
|
segment->OccupiedSize = newSize;
|
||||||
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, segment);
|
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, segment);
|
||||||
|
|
||||||
@@ -325,17 +327,18 @@ MIHP_HeapError MIHP_Free(MIHP_Heap* heap, void* ptr)
|
|||||||
|
|
||||||
if (segment->OccupiedSize == 0)
|
if (segment->OccupiedSize == 0)
|
||||||
{
|
{
|
||||||
MIHP_HeapCorruptionInfo corruptionInfo = { 0 };
|
MIHP_HeapCorruptionInfo corruptionInfo;
|
||||||
corruptionInfo.Error = MIHP_HCE_DoubleFree;
|
corruptionInfo.Error = MIHP_HCE_DoubleFree;
|
||||||
corruptionInfo.Ptr = ptr;
|
corruptionInfo.Ptr = ptr;
|
||||||
|
corruptionInfo.ExpectedValue = 0;
|
||||||
|
corruptionInfo.ActualValue = 0;
|
||||||
|
|
||||||
if (heap->Config.OnHeapCorruptionDetectedFn != NULL)
|
if (heap->Config.OnHeapCorruptionDetectedFn != NULL)
|
||||||
heap->Config.OnHeapCorruptionDetectedFn(heap, corruptionInfo);
|
heap->Config.OnHeapCorruptionDetectedFn(heap, corruptionInfo);
|
||||||
|
|
||||||
MIHP_UnlockHeap(heap);
|
|
||||||
return MIHP_HE_InvalidOperation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MIHP_MEMSET(ptr, heap->Config.FreeFillValue, segment->OccupiedSize);
|
||||||
|
|
||||||
segment->OccupiedSize = 0;
|
segment->OccupiedSize = 0;
|
||||||
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, segment);
|
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, segment);
|
||||||
|
|
||||||
@@ -463,7 +466,7 @@ MIHP_HeapError MIHP_MergeHeaps(MIHP_Heap* sourceHeap, MIHP_Heap* heapToAbsorb)
|
|||||||
sourceHeap->Stats.TotalSize += heapToAbsorb->Stats.TotalSize;
|
sourceHeap->Stats.TotalSize += heapToAbsorb->Stats.TotalSize;
|
||||||
|
|
||||||
MIHP_UnlockHeap(heapToAbsorb);
|
MIHP_UnlockHeap(heapToAbsorb);
|
||||||
MIHP_MEMSET(heapToAbsorb, sizeof(MIHP_Heap), 0);
|
MIHP_MEMSET(heapToAbsorb, 0, sizeof(MIHP_Heap));
|
||||||
|
|
||||||
sourceEndArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(sourceHeap, sourceEndArea);
|
sourceEndArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(sourceHeap, sourceEndArea);
|
||||||
sourceEndArea->NextArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(sourceHeap, sourceEndArea->NextArea);
|
sourceEndArea->NextArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(sourceHeap, sourceEndArea->NextArea);
|
||||||
@@ -607,8 +610,11 @@ MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_Heap* heap, size_t req
|
|||||||
if (area == NULL)
|
if (area == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
MIHP_ASSERT((uintptr_t)area % heap->Config.AllocationAlignment == 0);
|
||||||
|
MIHP_ASSERT(actualSize % heap->Config.AllocationAlignment == 0);
|
||||||
MIHP_ASSERT(actualSize >= effectiveSize);
|
MIHP_ASSERT(actualSize >= effectiveSize);
|
||||||
MIHP_MEMSET(area, sizeof(MIHP_HeapMemoryAreaHeader), 0);
|
|
||||||
|
MIHP_MEMSET(area, 0, sizeof(MIHP_HeapMemoryAreaHeader));
|
||||||
|
|
||||||
area->InstigatingHeap = (MIHP_HeapOpaque)heap;
|
area->InstigatingHeap = (MIHP_HeapOpaque)heap;
|
||||||
area->AreaSize = actualSize;
|
area->AreaSize = actualSize;
|
||||||
@@ -652,7 +658,7 @@ MIHP_HeapSegmentHeader* MIHP_InitializeHeapSegment(MIHP_Heap* heap, MIHP_HeapMem
|
|||||||
|
|
||||||
MIHP_HeapSegmentHeader* segment = (MIHP_HeapSegmentHeader*)segmentStart;
|
MIHP_HeapSegmentHeader* segment = (MIHP_HeapSegmentHeader*)segmentStart;
|
||||||
|
|
||||||
MIHP_MEMSET(segment, sizeof(MIHP_HeapSegmentHeader), 0);
|
MIHP_MEMSET(segment, 0, sizeof(MIHP_HeapSegmentHeader));
|
||||||
|
|
||||||
segment->SegmentSize = segmentSize;
|
segment->SegmentSize = segmentSize;
|
||||||
segment->OwningMemoryArea = area;
|
segment->OwningMemoryArea = area;
|
||||||
@@ -677,7 +683,7 @@ bool MIHP_UninitializeHeapSegment(MIHP_Heap* heap, MIHP_HeapSegmentHeader* segme
|
|||||||
segment->OwningMemoryArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, segment->OwningMemoryArea);
|
segment->OwningMemoryArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, segment->OwningMemoryArea);
|
||||||
heap->Stats.NumTotalSegments--;
|
heap->Stats.NumTotalSegments--;
|
||||||
|
|
||||||
MIHP_MEMSET(segment, sizeof(MIHP_HeapSegmentHeader), 0);
|
MIHP_MEMSET(segment, 0, sizeof(MIHP_HeapSegmentHeader));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#define MIHP_IMPLEMENTATION 1
|
#define MIHP_IMPLEMENTATION
|
||||||
#include "minimal_heap.h"
|
#include "minimal_heap.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user