diff --git a/minimal_heap.c b/minimal_heap.c new file mode 100644 index 0000000..9bcf359 --- /dev/null +++ b/minimal_heap.c @@ -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); + } +} + diff --git a/minimal_heap.h b/minimal_heap.h index 20a5dab..86c0435 100644 --- a/minimal_heap.h +++ b/minimal_heap.h @@ -4,107 +4,118 @@ #include #include -#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); -} \ No newline at end of file +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); +/* */ diff --git a/minimal_heap_test.c b/minimal_heap_test.c new file mode 100644 index 0000000..4e76e6e --- /dev/null +++ b/minimal_heap_test.c @@ -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() +{ +} + diff --git a/minimal_heap_test.sln b/minimal_heap_test.sln new file mode 100644 index 0000000..806e01c --- /dev/null +++ b/minimal_heap_test.sln @@ -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 diff --git a/minimal_heap_test.vcxproj b/minimal_heap_test.vcxproj new file mode 100644 index 0000000..9688f30 --- /dev/null +++ b/minimal_heap_test.vcxproj @@ -0,0 +1,136 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {58f662f6-eaac-4d4b-a2f5-c25ed48a05f7} + minimalheaptest + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdc17 + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/minimal_heap_test.vcxproj.filters b/minimal_heap_test.vcxproj.filters new file mode 100644 index 0000000..e9330a5 --- /dev/null +++ b/minimal_heap_test.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Quelldateien + + + Quelldateien + + + + + Headerdateien + + + \ No newline at end of file diff --git a/minimal_heap_test.vcxproj.user b/minimal_heap_test.vcxproj.user new file mode 100644 index 0000000..966b4ff --- /dev/null +++ b/minimal_heap_test.vcxproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file