| ... | ... | @@ -162,6 +162,10 @@ pub const Config = struct { |
| 162 | 162 | |
| 163 | 163 | /// Tell whether the backing allocator returns already-zeroed memory. |
| 164 | 164 | backing_allocator_zeroes: bool = true, |
| 165 | |
| 166 | /// Magic value that distinguishes allocations owned by this allocator from |
| 167 | /// other regions of memory. |
| 168 | canary: usize = @truncate(0x9232a6ff85dff10f), |
| 165 | 169 | }; |
| 166 | 170 | |
| 167 | 171 | pub const Check = enum { ok, leak }; |
| ... | ... | @@ -266,6 +270,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 266 | 270 | allocated_count: SlotIndex, |
| 267 | 271 | freed_count: SlotIndex, |
| 268 | 272 | prev: ?*BucketHeader, |
| 273 | canary: usize = config.canary, |
| 269 | 274 | |
| 270 | 275 | fn fromPage(page_addr: usize, slot_count: usize) *BucketHeader { |
| 271 | 276 | const unaligned = page_addr + page_size - bucketSize(slot_count); |
| ... | ... | @@ -832,6 +837,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 832 | 837 | const freed_addr = @intFromPtr(old_memory.ptr); |
| 833 | 838 | const page_addr = freed_addr & ~(page_size - 1); |
| 834 | 839 | const bucket: *BucketHeader = .fromPage(page_addr, slot_count); |
| 840 | if (bucket.canary != config.canary) @panic("Invalid free"); |
| 835 | 841 | const page_offset = freed_addr - page_addr; |
| 836 | 842 | const size_class = @as(usize, 1) << @as(u6, @intCast(size_class_index)); |
| 837 | 843 | const slot_index: SlotIndex = @intCast(page_offset / size_class); |