mirror of
https://github.com/ToyB-Chan/minimal-heap.git
synced 2026-07-13 21:51:16 +02:00
dev
This commit is contained in:
314
minimal_heap.c
Normal file
314
minimal_heap.c
Normal file
@@ -0,0 +1,314 @@
|
||||
#include "minimal_heap.h"
|
||||
|
||||
#define MIHP_MIN(A, B) (A) < (B) ? (A) : (B)
|
||||
#define MIHP_MAX(A, B) (A) > (B) ? (A) : (B)
|
||||
|
||||
MIHP_HeapInfo* MIHP_CreateHeap(size_t initialSize, size_t allocationAlignment)
|
||||
{
|
||||
MIHP_HeapInfo* heap = (MIHP_HeapInfo*)MIHP_PlatformRequestMemory(sizeof(MIHP_HeapInfo));
|
||||
if (heap == NULL)
|
||||
return NULL;
|
||||
|
||||
heap->FirstArea = MIHP_CreateHeapMemoryArea(heap, initialSize);
|
||||
if (heap->FirstArea == NULL)
|
||||
{
|
||||
MIHP_PlatformFreeMemory(heap, sizeof(MIHP_HeapInfo));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
heap->AllocationAlignment = allocationAlignment;
|
||||
return heap;
|
||||
}
|
||||
|
||||
bool MIHP_DestroyHeap(MIHP_HeapInfo* heap, bool force)
|
||||
{
|
||||
MIHP_ASSERT(heap);
|
||||
|
||||
if (!force && heap->Stats.NumTotalOccupiedSegments > 0)
|
||||
return false;
|
||||
|
||||
MIHP_HeapMemoryAreaHeader* nextArea = heap->FirstArea;
|
||||
while (nextArea)
|
||||
{
|
||||
MIHP_HeapMemoryAreaHeader* currentArea = nextArea;
|
||||
nextArea = currentArea->NextArea;
|
||||
MIHP_DestroyHeapMemoryArea(heap, currentArea);
|
||||
}
|
||||
|
||||
MIHP_PlatformFreeMemory(heap, sizeof(MIHP_HeapInfo));
|
||||
return true;
|
||||
}
|
||||
|
||||
void* MIHP_Allocate(MIHP_HeapInfo* heap, size_t size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MIHP_Free(MIHP_HeapInfo* heap, void* ptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool MIHP_IsPointerInHeap(MIHP_HeapInfo* heap, void* ptr)
|
||||
{
|
||||
MIHP_LOCK_HEAP(&heap->HeapLock);
|
||||
|
||||
size_t searchingPtr = (size_t)ptr;
|
||||
|
||||
MIHP_HeapMemoryAreaHeader* nextArea = heap->FirstArea;
|
||||
while (nextArea)
|
||||
{
|
||||
MIHP_HeapMemoryAreaHeader* currentArea = nextArea;
|
||||
nextArea = currentArea->NextArea;
|
||||
|
||||
size_t ptrMin = (size_t)currentArea;
|
||||
size_t ptrMax = (size_t)currentArea + currentArea->AreaSize;
|
||||
|
||||
if (searchingPtr >= ptrMin && searchingPtr <= ptrMax)
|
||||
{
|
||||
MIHP_UNLOCK_HEAP(&heap->HeapLock);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
MIHP_UNLOCK_HEAP(&heap->HeapLock);
|
||||
return false;
|
||||
}
|
||||
|
||||
void MIHP_ValidateHeap(MIHP_HeapInfo* heap)
|
||||
{
|
||||
}
|
||||
|
||||
MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_HeapInfo* heap, size_t requestedSize)
|
||||
{
|
||||
MIHP_ASSERT(heap);
|
||||
|
||||
size_t effectiveSize = ((requestedSize + MIHP_MINIMAL_MEMORY_AREA_SIZE - 1) / MIHP_MINIMAL_MEMORY_AREA_SIZE) * MIHP_MINIMAL_MEMORY_AREA_SIZE;
|
||||
|
||||
MIHP_HeapMemoryAreaHeader* area = MIHP_PlatformRequestMemory(effectiveSize);
|
||||
if (area == NULL)
|
||||
return NULL;
|
||||
|
||||
heap->Stats.NumMemoryAreas++;
|
||||
area->NextArea = NULL;
|
||||
area->PreviousArea = NULL;
|
||||
area->AreaSize = effectiveSize;
|
||||
area->NumOccupiedSegments = 0;
|
||||
area->NumSegments = 0;
|
||||
area->OwningHeap = heap;
|
||||
|
||||
size_t headerSize = MIHP_GetHeapAlignedSize(heap, sizeof(MIHP_HeapMemoryAreaHeader));
|
||||
area->FirstSegment = MIHP_InitializeHeapSegment(area, (char*)area + headerSize, area->AreaSize - headerSize);
|
||||
|
||||
area->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(area);
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
bool MIHP_DestroyHeapMemoryArea(MIHP_HeapInfo* heap, MIHP_HeapMemoryAreaHeader* memoryArea)
|
||||
{
|
||||
MIHP_ASSERT(heap);
|
||||
MIHP_ASSERT(memoryArea);
|
||||
|
||||
size_t areaNumSegments = memoryArea->NumSegments;
|
||||
size_t areaNumOccupiedSegments = memoryArea->NumOccupiedSegments;
|
||||
|
||||
if (!MIHP_PlatformFreeMemory(memoryArea, memoryArea->AreaSize))
|
||||
return false;
|
||||
|
||||
heap->Stats.NumTotalSegments -= areaNumSegments;
|
||||
heap->Stats.NumTotalOccupiedSegments -= areaNumOccupiedSegments;
|
||||
heap->Stats.NumMemoryAreas--;
|
||||
return true;
|
||||
}
|
||||
|
||||
MIHP_HeapSegmentHeader* MIHP_InitializeHeapSegment(MIHP_HeapMemoryAreaHeader* area, void* segmentStart, size_t segmentSize)
|
||||
{
|
||||
MIHP_ASSERT(area);
|
||||
MIHP_ASSERT(segmentStart);
|
||||
|
||||
MIHP_HeapSegmentHeader* segment = (MIHP_HeapSegmentHeader*)segmentStart;
|
||||
segment->SegmentSize = segmentSize;
|
||||
segment->OccupiedSize = 0;
|
||||
segment->NextSegment = NULL;
|
||||
segment->PreviousSegment = NULL;
|
||||
segment->OwningMemoryArea = area;
|
||||
|
||||
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(segment);
|
||||
|
||||
area->NumSegments++;
|
||||
area->OwningHeap->Stats.NumTotalSegments++;
|
||||
return segment;
|
||||
}
|
||||
|
||||
bool MIHP_UninitializeHeapSegment(MIHP_HeapSegmentHeader* segment)
|
||||
{
|
||||
MIHP_ASSERT(segment);
|
||||
|
||||
if (segment->OccupiedSize > 0)
|
||||
return false;
|
||||
|
||||
segment->OwningMemoryArea->NumSegments--;
|
||||
segment->OwningMemoryArea->OwningHeap->Stats.NumTotalSegments--;
|
||||
|
||||
#if MIHP_ZERO_OUT_MERGED_HEADERS
|
||||
segment->SegmentSize = 0;
|
||||
segment->OccupiedSize = 0;
|
||||
segment->NextSegment = NULL;
|
||||
segment->PreviousSegment = NULL;
|
||||
segment->OwningMemoryArea = NULL;
|
||||
segment->Checksum = 0;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MIHP_SplitHeapSegment(MIHP_HeapSegmentHeader* sourceSegment, size_t newSegmentMinSize, MIHP_HeapSegmentHeader** outNewSegment)
|
||||
{
|
||||
MIHP_ASSERT(sourceSegment);
|
||||
MIHP_ValidateHeapSegmentHeader(sourceSegment);
|
||||
MIHP_ValidateHeapMemoryAreaHeader(sourceSegment->OwningMemoryArea);
|
||||
|
||||
size_t headerSize = MIHP_GetHeapAlignedSize(sourceSegment->OwningMemoryArea->OwningHeap, sizeof(MIHP_HeapSegmentHeader));
|
||||
size_t effectiveNewSegmentSize = MIHP_GetHeapAlignedSize(sourceSegment->OwningMemoryArea->OwningHeap, newSegmentMinSize);
|
||||
|
||||
if (sourceSegment->SegmentSize < effectiveNewSegmentSize)
|
||||
return false;
|
||||
|
||||
size_t sourceResultingSegmentSize = sourceSegment->SegmentSize - effectiveNewSegmentSize;
|
||||
|
||||
if (sourceResultingSegmentSize < sourceSegment->OccupiedSize + headerSize)
|
||||
return false;
|
||||
|
||||
sourceSegment->SegmentSize = sourceResultingSegmentSize;
|
||||
|
||||
MIHP_HeapSegmentHeader* newSegment = MIHP_InitializeHeapSegment(sourceSegment->OwningMemoryArea, (char*)sourceSegment + sourceResultingSegmentSize, effectiveNewSegmentSize);
|
||||
newSegment->NextSegment = sourceSegment->NextSegment;
|
||||
newSegment->PreviousSegment = sourceSegment;
|
||||
|
||||
if (sourceSegment->NextSegment)
|
||||
sourceSegment->NextSegment->PreviousSegment = newSegment;
|
||||
|
||||
sourceSegment->NextSegment = newSegment;
|
||||
|
||||
if (outNewSegment)
|
||||
*outNewSegment = newSegment;
|
||||
|
||||
newSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(newSegment);
|
||||
sourceSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(sourceSegment);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MIHP_MergeHeapSegments(MIHP_HeapSegmentHeader* sourceSegment, MIHP_HeapSegmentHeader* segmentToAbsorb)
|
||||
{
|
||||
MIHP_ASSERT(sourceSegment);
|
||||
MIHP_ASSERT(segmentToAbsorb);
|
||||
MIHP_ASSERT(sourceSegment->NextSegment == segmentToAbsorb);
|
||||
|
||||
MIHP_ValidateHeapSegmentHeader(sourceSegment);
|
||||
MIHP_ValidateHeapSegmentHeader(segmentToAbsorb);
|
||||
MIHP_ValidateHeapMemoryAreaHeader(segmentToAbsorb->OwningMemoryArea);
|
||||
|
||||
if (segmentToAbsorb->OccupiedSize > 0)
|
||||
return false;
|
||||
|
||||
sourceSegment->NextSegment = segmentToAbsorb->NextSegment;
|
||||
|
||||
if (sourceSegment->NextSegment)
|
||||
sourceSegment->NextSegment->PreviousSegment = sourceSegment;
|
||||
|
||||
sourceSegment->SegmentSize += segmentToAbsorb->SegmentSize;
|
||||
MIHP_UninitializeHeapSegment(segmentToAbsorb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t MIHP_GetHeapAlignedSize(MIHP_HeapInfo* heap, size_t size)
|
||||
{
|
||||
return (size + (heap->AllocationAlignment - 1)) & ~(heap->AllocationAlignment - 1);
|
||||
}
|
||||
|
||||
uint32_t MIHP_HashMemoryRegion(const void* data, size_t size)
|
||||
{
|
||||
uint32_t hash = 2166136261U;
|
||||
const unsigned char* bytes = (const unsigned char*)data;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
hash ^= bytes[i];
|
||||
hash *= 16777619U;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint32_t MIHP_GenerateHeapMemoryAreaChecksum(const MIHP_HeapMemoryAreaHeader* area)
|
||||
{
|
||||
#if !MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
MIHP_ASSERT(area);
|
||||
|
||||
// Do not include the checksum itself into the new checksum
|
||||
size_t size = sizeof(MIHP_HeapMemoryAreaHeader) - sizeof(area->Checksum);
|
||||
return MIHP_HashMemoryRegion(area, size);
|
||||
}
|
||||
|
||||
uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_HeapSegmentHeader* segment)
|
||||
{
|
||||
#if !MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
MIHP_ASSERT(segment);
|
||||
|
||||
// Do not include the checksum itself into the new checksum
|
||||
size_t size = sizeof(MIHP_HeapSegmentHeader) - sizeof(segment->Checksum);
|
||||
return MIHP_HashMemoryRegion(segment, size);
|
||||
}
|
||||
|
||||
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapMemoryAreaHeader* area)
|
||||
{
|
||||
#if !MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION
|
||||
return;
|
||||
#endif
|
||||
|
||||
size_t newChecksum = MIHP_GenerateHeapMemoryAreaChecksum(area);
|
||||
|
||||
if (area->Checksum != newChecksum)
|
||||
{
|
||||
MIHP_HeapCorruptionInfo corruptionInfo;
|
||||
corruptionInfo.Type = MIHP_HEAP_CORRUPTION_TYPE_MEMORY_AREA_CHECKSUM_MISMATCH;
|
||||
corruptionInfo.Ptr = area;
|
||||
corruptionInfo.ExpectedValue = area->Checksum;
|
||||
corruptionInfo.ActualValue = newChecksum;
|
||||
|
||||
MIHP_PlatformOnHeapCorruptionDetected(corruptionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void MIHP_ValidateHeapSegmentHeader(const MIHP_HeapSegmentHeader* segment)
|
||||
{
|
||||
#if !MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION
|
||||
return;
|
||||
#endif
|
||||
|
||||
size_t newChecksum = MIHP_GenerateHeapSegmentChecksum(segment);
|
||||
|
||||
if (segment->Checksum != newChecksum)
|
||||
{
|
||||
MIHP_HeapCorruptionInfo corruptionInfo;
|
||||
corruptionInfo.Type = MIHP_HEAP_CORRUPTION_TYPE_SEGMENT_CHECKSUM_MISMATCH;
|
||||
corruptionInfo.Ptr = segment;
|
||||
corruptionInfo.ExpectedValue = segment->Checksum;
|
||||
corruptionInfo.ActualValue = newChecksum;
|
||||
|
||||
MIHP_PlatformOnHeapCorruptionDetected(corruptionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
171
minimal_heap.h
171
minimal_heap.h
@@ -4,107 +4,118 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define USE_HEAP_STRUCTURE_CHECKSUM 1
|
||||
#define USE_CANARY_VALIDATION 1
|
||||
#define MIHP_USE_HEAP_STRUCTURE_CHECKSUM_VALIDATION 1
|
||||
#define MIHP_USE_CANARY_VALIDATION 1
|
||||
|
||||
#define HEAP_CORRUPTION_TYPE_MEMORY_AREA_CHECKSUM_MISMATCH 0
|
||||
#define HEAP_CORRUPTION_TYPE_SEGMENT_CHECKSUM_MISMATCH 1
|
||||
#define HEAP_CORRUPTION_TYPE_FRONT_CANARY_MISMATCH 2
|
||||
#define HEAP_CORRUPTION_TYPE_REAR_CANARY_MISMATCH 3
|
||||
#define MIHP_ZERO_OUT_MERGED_HEADERS 1
|
||||
#define MIHP_ZERO_OUT_ALLOCATIONS 1
|
||||
|
||||
struct heap_stats
|
||||
#define MIHP_HEAP_CORRUPTION_TYPE_MEMORY_AREA_CHECKSUM_MISMATCH 0
|
||||
#define MIHP_HEAP_CORRUPTION_TYPE_SEGMENT_CHECKSUM_MISMATCH 1
|
||||
#define MIHP_HEAP_CORRUPTION_TYPE_FRONT_CANARY_MISMATCH 2
|
||||
#define MIHP_HEAP_CORRUPTION_TYPE_REAR_CANARY_MISMATCH 3
|
||||
|
||||
typedef struct _MIHP_HeapStats
|
||||
{
|
||||
size_t num_memory_areas;
|
||||
size_t num_total_segments;
|
||||
size_t num_total_occupied_segments;
|
||||
size_t total_size;
|
||||
} typedef heap_stats;
|
||||
size_t NumMemoryAreas;
|
||||
size_t NumTotalSegments;
|
||||
size_t NumTotalOccupiedSegments;
|
||||
size_t TotalSize;
|
||||
} MIHP_HeapStats;
|
||||
|
||||
struct heap_memory_area
|
||||
// This structs size must be multiple of 8
|
||||
typedef struct _MIHP_HeapMemoryAreaHeader
|
||||
{
|
||||
size_t size;
|
||||
size_t num_segments;
|
||||
size_t num_occupied_segments;
|
||||
heap_memory_area* next_area;
|
||||
heap_memory_area* previous_area;
|
||||
size_t AreaSize;
|
||||
size_t NumSegments;
|
||||
size_t NumOccupiedSegments;
|
||||
|
||||
#if USE_HEAP_STRUCTURE_CHECKSUM
|
||||
uint32_t checksum;
|
||||
#endif
|
||||
} typedef heap_memory_area;
|
||||
struct _MIHP_HeapMemoryAreaHeader* NextArea;
|
||||
struct _MIHP_HeapMemoryAreaHeader* PreviousArea;
|
||||
|
||||
struct heap_segment
|
||||
struct _MIHP_HeapInfo* OwningHeap;
|
||||
struct _MIHP_HeapSegmentHeader* FirstSegment;
|
||||
|
||||
|
||||
uint32_t Checksum; // Checksum must be the last member !
|
||||
} MIHP_HeapMemoryAreaHeader;
|
||||
|
||||
// This structs size must be multiple of 8
|
||||
typedef struct _MIHP_HeapSegmentHeader
|
||||
{
|
||||
size_t size;
|
||||
bool is_occupied;
|
||||
size_t SegmentSize;
|
||||
size_t OccupiedSize;
|
||||
|
||||
heap_segment* next_segment;
|
||||
heap_segment* previous_segment;
|
||||
heap_memory_area* encapsulating_memory_area;
|
||||
struct _MIHP_HeapSegmentHeader* NextSegment;
|
||||
struct _MIHP_HeapSegmentHeader* PreviousSegment;
|
||||
struct _MIHP_HeapMemoryAreaHeader* OwningMemoryArea;
|
||||
|
||||
#if USE_HEAP_STRUCTURE_CHECKSUM
|
||||
uint32_t checksum;
|
||||
#endif
|
||||
} typedef heap_segment;
|
||||
char _padding0[16];
|
||||
|
||||
struct heap_corruption_info
|
||||
uint32_t Checksum; // Checksum must be the last member !
|
||||
|
||||
} MIHP_HeapSegmentHeader;
|
||||
|
||||
typedef struct _MIHP_HeapCorruptionInfo
|
||||
{
|
||||
uint8_t type;
|
||||
void* ptr;
|
||||
uint32_t expected_value;
|
||||
uint32_t actual_value;
|
||||
} typedef heap_corruption_info;
|
||||
uint8_t Type;
|
||||
const void* Ptr;
|
||||
uint32_t ExpectedValue;
|
||||
uint32_t ActualValue;
|
||||
} MIHP_HeapCorruptionInfo;
|
||||
|
||||
/* Hooks to be implemented by the library user */
|
||||
void* platform_request_memory_area(size_t size);
|
||||
bool platform_free_memory_area(void* ptr, size_t size);
|
||||
uint8_t platform_get_required_memory_alingment();
|
||||
void platform_heap_corruption_detected(heap_corruption_info info);
|
||||
|
||||
size_t config_minimal_memory_area_size();
|
||||
size_t config_minimal_amount_unoccupied_bytes();
|
||||
size_t config_minimal_amount_unoccupied_continuous_bytes();
|
||||
void* MIHP_PlatformRequestMemory(size_t size); // Alignment must at least be alingment of size_t
|
||||
bool MIHP_PlatformFreeMemory(void* ptr, size_t size);
|
||||
void MIHP_PlatformOnHeapCorruptionDetected(MIHP_HeapCorruptionInfo info);
|
||||
/* === */
|
||||
|
||||
uint32_t fast_memory_hasher(const void* data, size_t size)
|
||||
/* Defines to be configured by the library user */
|
||||
#define MIHP_MINIMAL_MEMORY_AREA_SIZE (4096 * 32)
|
||||
|
||||
#define MIHP_ASSERT(Condition) do { if (Condition) break; *(volatile char*)(0x0) = 0; } while(1)
|
||||
|
||||
#define MIHP_HEAP_LOCK_TYPE uint8_t
|
||||
#define MIHP_LOCK_HEAP(LockVariablePtr) {}
|
||||
#define MIHP_UNLOCK_HEAP(LockVarialbePtr) {}
|
||||
/* === */
|
||||
|
||||
typedef struct _MIHP_HeapInfo
|
||||
{
|
||||
uint32_t hash = 2166136261U;
|
||||
const unsigned char* bytes = (const unsigned char*)data;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
hash ^= bytes[i];
|
||||
hash *= 16777619U;
|
||||
}
|
||||
MIHP_HeapStats Stats;
|
||||
size_t AllocationAlignment;
|
||||
MIHP_HeapMemoryAreaHeader* FirstArea;
|
||||
|
||||
return hash;
|
||||
}
|
||||
MIHP_HEAP_LOCK_TYPE HeapLock;
|
||||
} MIHP_HeapInfo;
|
||||
|
||||
uint32_t generate_heap_memory_area_checksum(const heap_memory_area* area)
|
||||
{
|
||||
size_t checksum_size;
|
||||
/* API Interface */
|
||||
MIHP_HeapInfo* MIHP_CreateHeap(size_t initialSize, size_t allocationAlignment);
|
||||
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);
|
||||
void MIHP_Free(MIHP_HeapInfo* heap, void* ptr);
|
||||
|
||||
#if USE_HEAP_STRUCTURE_CHECKSUM
|
||||
checksum_size = sizeof(area->checksum);
|
||||
#else
|
||||
checksum_size = 0;
|
||||
#endif
|
||||
bool MIHP_IsPointerInHeap(MIHP_HeapInfo* heap, void* ptr);
|
||||
void MIHP_ValidateHeap(MIHP_HeapInfo* heap);
|
||||
/* */
|
||||
|
||||
// Do not include the checksum itself into the new checksum
|
||||
size_t size = sizeof(*area) - checksum_size;
|
||||
return fast_memory_hasher(area, size);
|
||||
}
|
||||
/* Internals */
|
||||
MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_HeapInfo* heap, size_t requestedSize);
|
||||
bool MIHP_DestroyHeapMemoryArea(MIHP_HeapInfo* heap, MIHP_HeapMemoryAreaHeader* area);
|
||||
|
||||
uint32_t generate_heap_segment_checksum(const heap_segment* segment)
|
||||
{
|
||||
size_t checksum_size;
|
||||
MIHP_HeapSegmentHeader* MIHP_InitializeHeapSegment(MIHP_HeapMemoryAreaHeader* area, void* segmentStart, size_t size);
|
||||
bool MIHP_UninitializeHeapSegment(MIHP_HeapSegmentHeader* segment);
|
||||
|
||||
#if USE_HEAP_STRUCTURE_CHECKSUM
|
||||
checksum_size = sizeof(segment->checksum);
|
||||
#else
|
||||
checksum_size = 0;
|
||||
#endif
|
||||
bool MIHP_SplitHeapSegment(MIHP_HeapSegmentHeader* sourceSegment, size_t newSegmentSize, MIHP_HeapSegmentHeader** outNewSegment);
|
||||
bool MIHP_MergeHeapSegments(MIHP_HeapSegmentHeader* sourceSegment, MIHP_HeapSegmentHeader* segmentToAbsorb);
|
||||
|
||||
// Do not include the checksum itself into the new checksum
|
||||
size_t size = sizeof(*segment) - checksum_size;
|
||||
return fast_memory_hasher(segment, size);
|
||||
}
|
||||
size_t MIHP_GetHeapAlignedSize(MIHP_HeapInfo* 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_HeapMemoryAreaHeader* area);
|
||||
void MIHP_ValidateHeapSegmentHeader(const MIHP_HeapSegmentHeader* segment);
|
||||
/* */
|
||||
|
||||
26
minimal_heap_test.c
Normal file
26
minimal_heap_test.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "minimal_heap.h"
|
||||
|
||||
void* MIHP_PlatformRequestMemory(size_t size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool MIHP_PlatformFreeMemory(void* ptr, size_t size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint8_t MIHP_PlatformGetMinimalMemoryAlignment()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MIHP_PlatformOnHeapCorruptionDetected(MIHP_HeapCorruptionInfo info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
}
|
||||
|
||||
31
minimal_heap_test.sln
Normal file
31
minimal_heap_test.sln
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36717.8 d17.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minimal_heap_test", "minimal_heap_test.vcxproj", "{58F662F6-EAAC-4D4B-A2F5-C25ED48A05F7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{58F662F6-EAAC-4D4B-A2F5-C25ED48A05F7}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{58F662F6-EAAC-4D4B-A2F5-C25ED48A05F7}.Debug|x64.Build.0 = Debug|x64
|
||||
{58F662F6-EAAC-4D4B-A2F5-C25ED48A05F7}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{58F662F6-EAAC-4D4B-A2F5-C25ED48A05F7}.Debug|x86.Build.0 = Debug|Win32
|
||||
{58F662F6-EAAC-4D4B-A2F5-C25ED48A05F7}.Release|x64.ActiveCfg = Release|x64
|
||||
{58F662F6-EAAC-4D4B-A2F5-C25ED48A05F7}.Release|x64.Build.0 = Release|x64
|
||||
{58F662F6-EAAC-4D4B-A2F5-C25ED48A05F7}.Release|x86.ActiveCfg = Release|Win32
|
||||
{58F662F6-EAAC-4D4B-A2F5-C25ED48A05F7}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {4273B178-AE5C-4FCB-99D3-ACA9EE4C7E80}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
136
minimal_heap_test.vcxproj
Normal file
136
minimal_heap_test.vcxproj
Normal file
@@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{58f662f6-eaac-4d4b-a2f5-c25ed48a05f7}</ProjectGuid>
|
||||
<RootNamespace>minimalheaptest</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="minimal_heap.c" />
|
||||
<ClCompile Include="minimal_heap_test.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="minimal_heap.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
30
minimal_heap_test.vcxproj.filters
Normal file
30
minimal_heap_test.vcxproj.filters
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Quelldateien">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Headerdateien">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Ressourcendateien">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="minimal_heap_test.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="minimal_heap.c">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="minimal_heap.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
6
minimal_heap_test.vcxproj.user
Normal file
6
minimal_heap_test.vcxproj.user
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ShowAllFiles>true</ShowAllFiles>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user