// Enable this to enable checking for invalid blocks and other corruptions
// that may happen on the heap, with the added overhead of checking that
// on every alloc/resize/free.
-Enable_Debug :: #defined( runtime.vars.Enable_Heap_Debug ) || true
+Enable_Debug :: #defined( runtime.vars.Enable_Heap_Debug )
// This is the implementation for the general purpose heap allocator.
// It is a simple bump allocator, with a free list. It is not very good
heap_block :: struct {
size : u32;
- magic_number : u32;
}
heap_freed_block :: struct {
use base: heap_block;
+ magic_number : u32;
next : ^heap_freed_block;
prev : ^heap_freed_block;
}
use base: heap_block;
}
- Allocated_Flag :: 0x1
- Free_Block_Magic_Number :: 0xdeadbeef
- Alloc_Block_Magic_Number :: 0xbabecafe
- Block_Split_Size :: 256
+ Allocated_Flag :: 0x1
+ Free_Block_Magic_Number :: 0xdeadbeef
+ Block_Split_Size :: 256
+ // FIX: This does not respect the choice of alignment
heap_alloc :: (size_: u32, align: u32) -> rawptr {
if size_ == 0 do return null;
best.next = null;
best.prev = null;
- best.magic_number = Alloc_Block_Magic_Number;
+ best.magic_number = 0;
best.size |= Allocated_Flag;
return cast(rawptr) (cast(uintptr) best + sizeof heap_allocated_block);
-
- // nocheckin
}
if size < heap_state.remaining_space {
ret := cast(^heap_allocated_block) heap_state.next_alloc;
ret.size = size;
ret.size |= Allocated_Flag;
- ret.magic_number = Alloc_Block_Magic_Number;
heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + size);
heap_state.remaining_space -= size;
ret := cast(^heap_allocated_block) heap_state.next_alloc;
ret.size = size;
ret.size |= Allocated_Flag;
- ret.magic_number = Alloc_Block_Magic_Number;
heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + size);
heap_state.remaining_space -= size;
hb_ptr := cast(^heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
#if Enable_Debug {
- assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on free. This could be due to a double free, or using memory past were you allocated it.");
- assert(hb_ptr.magic_number == Alloc_Block_Magic_Number, "Freeing an unallocated pointer.");
+ // assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on free. This could be due to a double free, or using memory past were you allocated it.");
if cast(uintptr) hb_ptr < cast(uintptr) __heap_start {
log("FREEING STATIC DATA");
log("INVALID DOUBLE FREE");
return;
}
-
- // if hb_ptr.magic_number != Alloc_Block_Magic_Number {
- // log("INVALID FREE");
- // return;
- // }
}
hb_ptr.size &= ~Allocated_Flag;
hb_ptr := cast(^heap_allocated_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
#if Enable_Debug do assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on resize.");
- #if Enable_Debug do assert(hb_ptr.magic_number == Alloc_Block_Magic_Number, "Corrupted heap on resize.");
hb_ptr.size &= ~Allocated_Flag;
old_size := hb_ptr.size;
hb_ptr.size = new_size;
hb_ptr.size |= Allocated_Flag;
- hb_ptr.magic_number = Alloc_Block_Magic_Number;
heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + needed_size);
heap_state.remaining_space -= needed_size;
return ptr;
}
hb_ptr.size |= Allocated_Flag;
- hb_ptr.magic_number = Alloc_Block_Magic_Number;
new_ptr := heap_alloc(new_size_, align);
#if runtime.Multi_Threading_Enabled do sync.mutex_lock(^heap_mutex);