@@ -4,6 +4,7 @@ package core.alloc.heap
4
4
// that may happen on the heap, with the added overhead of checking that
5
5
// on every alloc/resize/free.
6
6
Enable_Debug :: #defined( runtime.vars.Enable_Heap_Debug )
7
+ Enable_Clear_Freed_Memory :: #defined(runtime.vars.Enable_Heap_Clear_Freed_Memory)
7
8
8
9
// This is the implementation for the general purpose heap allocator.
9
10
// It is a simple bump allocator, with a free list. It is not very good
@@ -63,11 +64,11 @@ get_freed_size :: () => {
63
64
64
65
heap_block :: struct {
65
66
size : u32;
67
+ magic_number : u32;
66
68
}
67
69
68
70
heap_freed_block :: struct {
69
71
use base: heap_block;
70
- magic_number : u32;
71
72
next : ^heap_freed_block;
72
73
prev : ^heap_freed_block;
73
74
}
@@ -76,9 +77,10 @@ get_freed_size :: () => {
76
77
use base: heap_block;
77
78
}
78
79
79
- Allocated_Flag :: 0x1
80
- Free_Block_Magic_Number :: 0xdeadbeef
81
- Block_Split_Size :: 256
80
+ Allocated_Flag :: 0x1
81
+ Free_Block_Magic_Number :: 0xdeadbeef
82
+ Alloc_Block_Magic_Number :: 0xbabecafe
83
+ Block_Split_Size :: 256
82
84
83
85
// FIX: This does not respect the choice of alignment
84
86
heap_alloc :: (size_: u32, align: u32) -> rawptr {
@@ -137,13 +139,15 @@ get_freed_size :: () => {
137
139
best.prev = null;
138
140
best.magic_number = 0;
139
141
best.size |= Allocated_Flag;
142
+ best.magic_number = Alloc_Block_Magic_Number;
140
143
return cast(rawptr) (cast(uintptr) best + sizeof heap_allocated_block);
141
144
}
142
145
143
146
if size < heap_state.remaining_space {
144
147
ret := cast(^heap_allocated_block) heap_state.next_alloc;
145
148
ret.size = size;
146
149
ret.size |= Allocated_Flag;
150
+ ret.magic_number = Alloc_Block_Magic_Number;
147
151
148
152
heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + size);
149
153
heap_state.remaining_space -= size;
@@ -161,6 +165,7 @@ get_freed_size :: () => {
161
165
ret := cast(^heap_allocated_block) heap_state.next_alloc;
162
166
ret.size = size;
163
167
ret.size |= Allocated_Flag;
168
+ ret.magic_number = Alloc_Block_Magic_Number;
164
169
165
170
heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + size);
166
171
heap_state.remaining_space -= size;
@@ -185,12 +190,19 @@ get_freed_size :: () => {
185
190
log("INVALID DOUBLE FREE");
186
191
return;
187
192
}
193
+
194
+ if hb_ptr.magic_number != Alloc_Block_Magic_Number {
195
+ log("FREEING INVALID BLOCK");
196
+ return;
197
+ }
188
198
}
189
199
190
200
hb_ptr.size &= ~Allocated_Flag;
191
201
orig_size := hb_ptr.size - sizeof heap_allocated_block;
192
202
193
- #if Enable_Debug do memory_fill(ptr, ~~0xcc, orig_size);
203
+ #if Enable_Debug && Enable_Clear_Freed_Memory {
204
+ memory_fill(ptr, ~~0xcc, orig_size);
205
+ }
194
206
195
207
if cast(uintptr) hb_ptr + hb_ptr.size < cast(uintptr) heap_state.next_alloc {
196
208
next_block := cast(^heap_freed_block) (cast(uintptr) hb_ptr + hb_ptr.size);
@@ -275,6 +287,7 @@ get_freed_size :: () => {
275
287
276
288
hb_ptr.size = new_size;
277
289
hb_ptr.size |= Allocated_Flag;
290
+ hb_ptr.magic_number = Alloc_Block_Magic_Number;
278
291
heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + needed_size);
279
292
heap_state.remaining_space -= needed_size;
280
293
return ptr;
0 commit comments