tiny.deadalloc.DeadAllocator
Defined in tiny.deadalloc.
API (22)
Actions
Public operations.
Fields and members
Public fields and members.
backing_allocatorclassesconfigcountersepochissuesknownlarge_quarantinelast_issuelivemutexnext_allocation_idpage_ownersprng
Source
Source: lib/deadalloc/src/allocator.zig:173
zig
pub const DeadAllocator = struct { backing_allocator: Allocator, config: Config, classes: [size_class.count]ClassState = @as([size_class.count]ClassState, @splat(.{})), live: std.AutoHashMap(usize, AllocationRecord), known: std.AutoHashMap(usize, AllocationRecord), page_owners: std.AutoHashMap(usize, usize), large_quarantine: std.ArrayList(AllocationRecord) = .empty, prng: std.Random.DefaultPrng, mutex: std.atomic.Mutex = .unlocked, epoch: u64 = 1, next_allocation_id: u64 = 1, counters: report_mod.Counters = .{}, last_issue: ?Issue = null, issues: report_mod.IssueLog = .{}, const Self = @This(); pub fn init(backing_allocator: Allocator, config: Config) Self { std.debug.assert(config.numerator >= config.denominator); std.debug.assert(config.denominator > 0); return .{ .backing_allocator = backing_allocator, .config = config, .live = std.AutoHashMap(usize, AllocationRecord).init(backing_allocator), .known = std.AutoHashMap(usize, AllocationRecord).init(backing_allocator), .page_owners = std.AutoHashMap(usize, usize).init(backing_allocator), .prng = std.Random.DefaultPrng.init(config.seed), }; } pub fn deinit(self: *Self) void { if (self.diagnosticsActive()) { self.counters.invalid_free += 0; } self.releaseLiveLargeAllocations(@returnAddress()); for (self.large_quarantine.items) |record| self.releaseLarge(record, @returnAddress()); self.large_quarantine.deinit(self.backing_allocator); for (&self.classes) |*class_state| class_state.deinit(self.backing_allocator, self); self.live.deinit(); self.known.deinit(); self.page_owners.deinit(); self.* = undefined; } pub fn allocator(self: *Self) Allocator { return .{ .ptr = self, .vtable = &vtable, }; } pub fn report(self: *Self) Report { self.lock(); defer self.unlock(); const ret_addr = @returnAddress(); self.scanLiveCanaries(ret_addr); self.scanFreedMemory(ret_addr); self.drainLargeQuarantine(ret_addr); return self.reportUnlocked(ret_addr); } fn reportUnlocked(self: *Self, ret_addr: usize) Report { var live_bytes: usize = 0; var leak_issue: ?Issue = null; var issues = self.issues; var iterator = self.live.valueIterator(); while (iterator.next()) |record| { live_bytes += record.requested_len; const issue: Issue = .{ .kind = .leak, .address = record.address, .requested_len = record.requested_len, .block_size = record.block_size, .allocation_id = record.allocation_id, .allocation_return_address = record.allocation_return_address, .return_address = ret_addr, }; if (leak_issue == null) leak_issue = issue; issues.append(issue); } return .{ .counters = self.counters, .live_allocations = self.live.count(), .live_bytes = live_bytes, .leak_count = self.live.count(), .leak_issue = leak_issue, .last_issue = self.last_issue, .issues = issues, }; } pub fn rawAlloc(self: *Self, len: usize, alignment: Alignment, ret_addr: usize) ?[*]u8 { self.lock(); defer self.unlock(); self.drainLargeQuarantine(ret_addr); const repair_padding = self.config.repairPadding(ret_addr); const total_len = self.totalAllocationLen(len, repair_padding) orelse return null; const class_index = size_class.indexFor(total_len, alignment) orelse return self.allocateLarge(len, repair_padding, total_len, alignment, ret_addr); return self.allocateSmall(class_index, len, repair_padding, total_len, alignment, ret_addr) catch null; } pub fn rawResize(self: *Self, memory: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) bool { self.lock(); defer self.unlock(); self.drainLargeQuarantine(ret_addr); const address = @intFromPtr(memory.ptr); const record_ptr = self.live.getPtr(address) orelse { self.recordUnknownFree(address, memory.len, alignment, ret_addr); return false; }; if (memory.len != record_ptr.requested_len) { self.recordIssue(.{ .kind = .size_mismatch, .address = address, .requested_len = memory.len, .block_size = record_ptr.block_size, .allocation_id = record_ptr.allocation_id, .allocation_return_address = record_ptr.allocation_return_address, .free_return_address = record_ptr.free_return_address, .free_epoch = record_ptr.free_epoch, .return_address = ret_addr, }); } _ = self.checkCanary(record_ptr, ret_addr); const total_len = self.totalAllocationLen(new_len, record_ptr.repair_padding) orelse return false; if (total_len > record_ptr.block_size) return false; if (record_ptr.kind == .small) { const block = record_ptr.small_block.?; block.chunk.requested_lens[block.index] = new_len; } record_ptr.requested_len = new_len; record_ptr.canary_issue_reported = false; if (self.known.getPtr(address)) |known| known.requested_len = new_len; self.installCanary(@ptrFromInt(address), new_len, record_ptr.repair_padding, record_ptr.block_size); return true; } pub fn rawRemap(self: *Self, memory: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) ?[*]u8 { if (self.rawResize(memory, alignment, new_len, ret_addr)) return memory.ptr; const address = @intFromPtr(memory.ptr); const old_len = old_len: { self.lock(); defer self.unlock(); const record = self.live.get(address) orelse return null; break :old_len record.requested_len; }; const new_ptr = self.rawAlloc(new_len, alignment, ret_addr) orelse return null; const copy_len = @min(old_len, new_len); const old_ptr: [*]u8 = @ptrFromInt(address); @memcpy(new_ptr[0..copy_len], old_ptr[0..copy_len]); self.rawFree(old_ptr[0..old_len], alignment, ret_addr); return new_ptr; } pub fn rawFree(self: *Self, memory: []u8, alignment: Alignment, ret_addr: usize) void { self.lock(); defer self.unlock(); const address = @intFromPtr(memory.ptr); var record = self.live.fetchRemove(address) orelse { self.recordUnknownFree(address, memory.len, alignment, ret_addr); return; }; if (memory.len != record.value.requested_len) { self.recordIssue(.{ .kind = .size_mismatch, .address = address, .requested_len = memory.len, .block_size = record.value.block_size, .allocation_id = record.value.allocation_id, .allocation_return_address = record.value.allocation_return_address, .free_return_address = record.value.free_return_address, .free_epoch = record.value.free_epoch, .return_address = ret_addr, }); } _ = self.checkCanary(&record.value, ret_addr); switch (record.value.kind) { .small => self.freeSmall(&record.value, ret_addr), .large => self.freeLarge(&record.value, ret_addr), } if (self.known.getPtr(address)) |known| known.* = record.value; } fn allocateSmall( self: *Self, class_index: usize, requested_len: usize, repair_padding: usize, total_len: usize, alignment: Alignment, ret_addr: usize, ) ![*]u8 { const class_state = &self.classes[class_index]; if (self.shouldGrow(class_state)) try self.addChunk(class_index, ret_addr); const total_capacity = class_state.capacity; if (total_capacity == 0) return error.OutOfMemory; var attempts: usize = 0; while (attempts < total_capacity) : (attempts += 1) { const ordinal = self.prng.random().int(usize) % total_capacity; if (try self.tryAllocateSmallBlock( class_state, ordinal, requested_len, repair_padding, total_len, alignment, ret_addr, )) |ptr| return ptr; } var ordinal = self.prng.random().int(usize) % total_capacity; var probes: usize = 0; while (probes < total_capacity) : (probes += 1) { if (try self.tryAllocateSmallBlock( class_state, ordinal, requested_len, repair_padding, total_len, alignment, ret_addr, )) |ptr| return ptr; ordinal = (ordinal + 1) % total_capacity; } try self.addChunk(class_index, ret_addr); return self.allocateSmall(class_index, requested_len, repair_padding, total_len, alignment, ret_addr); } fn tryAllocateSmallBlock( self: *Self, class_state: *ClassState, ordinal: usize, requested_len: usize, repair_padding: usize, total_len: usize, alignment: Alignment, ret_addr: usize, ) !?[*]u8 { const selected = self.blockByOrdinal(class_state, ordinal); const chunk = selected.chunk; const index = selected.index; if (!chunk.isAvailable(index, self.epoch)) return null; const ptr = chunk.blockPtr(index); if (!std.mem.isAligned(@intFromPtr(ptr), alignment.toByteUnits())) return null; if (self.diagnosticsActive() and chunk.states[index] == .free and !chunk.free_issue_reported[index]) { chunk.free_issue_reported[index] = self.checkFreedPattern( ptr, chunk.block_size, chunk.requested_lens[index], chunk.allocation_ids[index], chunk.allocation_return_addresses[index], chunk.free_return_addresses[index], chunk.free_epochs[index], chunk.free_patterns[index], ret_addr, ); } try self.ensurePageOwnerCapacityFor(@intFromPtr(ptr), chunk.block_size); const allocation_id = self.nextAllocationId(); chunk.states[index] = .live; chunk.free_issue_reported[index] = false; chunk.requested_lens[index] = requested_len; chunk.repair_paddings[index] = repair_padding; chunk.allocation_ids[index] = allocation_id; chunk.allocation_return_addresses[index] = ret_addr; chunk.free_return_addresses[index] = 0; chunk.live_count += 1; class_state.live_count += 1; self.epoch +%= 1; @memset(ptr[0..@min(requested_len, chunk.block_size)], allocated_byte); self.installCanary(ptr, requested_len, repair_padding, chunk.block_size); const record: AllocationRecord = .{ .kind = .small, .address = @intFromPtr(ptr), .requested_len = requested_len, .repair_padding = repair_padding, .block_size = chunk.block_size, .backing_len = total_len, .alignment = alignment, .allocation_id = allocation_id, .allocation_return_address = ret_addr, .small_block = .{ .chunk = chunk, .index = index }, }; self.live.put(record.address, record) catch { var cleanup = record; self.freeSmall(&cleanup, ret_addr); return error.OutOfMemory; }; self.known.put(record.address, record) catch { _ = self.live.remove(record.address); var cleanup = record; self.freeSmall(&cleanup, ret_addr); return error.OutOfMemory; }; self.putPageOwnerAssumeCapacity(record); return ptr; } fn allocateLarge(self: *Self, requested_len: usize, repair_padding: usize, backing_len: usize, alignment: Alignment, ret_addr: usize) ?[*]u8 { const effective_backing_len = self.largeBackingLen(backing_len) orelse return null; const effective_alignment = self.largeAlignment(alignment); const ptr = self.backing_allocator.rawAlloc(effective_backing_len, effective_alignment, ret_addr) orelse return null; @memset(ptr[0..@min(requested_len, effective_backing_len)], allocated_byte); self.installCanary(ptr, requested_len, repair_padding, effective_backing_len); const allocation_id = self.nextAllocationId(); const record: AllocationRecord = .{ .kind = .large, .address = @intFromPtr(ptr), .requested_len = requested_len, .repair_padding = repair_padding, .block_size = effective_backing_len, .backing_len = effective_backing_len, .alignment = effective_alignment, .allocation_id = allocation_id, .allocation_return_address = ret_addr, }; self.ensurePageOwnerCapacity(record) catch { self.backing_allocator.rawFree(ptr[0..effective_backing_len], effective_alignment, ret_addr); return null; }; self.live.put(record.address, record) catch { self.backing_allocator.rawFree(ptr[0..effective_backing_len], effective_alignment, ret_addr); return null; }; self.known.put(record.address, record) catch { _ = self.live.remove(record.address); self.backing_allocator.rawFree(ptr[0..effective_backing_len], effective_alignment, ret_addr); return null; }; self.putPageOwnerAssumeCapacity(record); return ptr; } fn largeBackingLen(self: *const Self, backing_len: usize) ?usize { return switch (self.config.mode) { .dieharder => alignForwardChecked(backing_len, page_size), .diehard, .exterminator => backing_len, }; } fn largeAlignment(self: *const Self, alignment: Alignment) Alignment { return switch (self.config.mode) { .dieharder => .fromByteUnits(@max(alignment.toByteUnits(), page_size)), .diehard, .exterminator => alignment, }; } fn freeSmall(self: *Self, record: *AllocationRecord, ret_addr: usize) void { const block = record.small_block.?; const chunk = block.chunk; const ptr = chunk.blockPtr(block.index); record.free_pattern = self.nextFreedPattern(); if (self.writeFreedPattern()) self.fillFreedPattern(ptr, chunk.block_size, record.free_pattern); record.free_return_address = ret_addr; record.free_epoch = self.epoch; record.free_quarantine_epochs = self.config.repairQuarantineEpochs(record.allocation_return_address, ret_addr); chunk.states[block.index] = .free; chunk.free_return_addresses[block.index] = ret_addr; chunk.free_epochs[block.index] = self.epoch; chunk.free_quarantine_epochs[block.index] = record.free_quarantine_epochs; chunk.free_patterns[block.index] = record.free_pattern; chunk.free_issue_reported[block.index] = false; chunk.live_count -= 1; self.classes[chunk.class_index].live_count -= 1; self.epoch +%= 1; } fn freeLarge(self: *Self, record: *AllocationRecord, ret_addr: usize) void { const ptr: [*]u8 = @ptrFromInt(record.address); record.free_pattern = self.nextFreedPattern(); if (self.writeFreedPattern()) self.fillFreedPattern(ptr, record.backing_len, record.free_pattern); record.free_return_address = ret_addr; record.free_epoch = self.epoch; record.free_quarantine_epochs = self.config.repairQuarantineEpochs(record.allocation_return_address, ret_addr); if (record.free_quarantine_epochs > 0) { var quarantined = record.*; quarantined.free_issue_reported = false; self.large_quarantine.append(self.backing_allocator, quarantined) catch { self.releaseLarge(record.*, ret_addr); return; }; self.epoch +%= 1; return; } self.releaseLarge(record.*, ret_addr); } fn releaseLarge(self: *Self, record: AllocationRecord, ret_addr: usize) void { const ptr: [*]u8 = @ptrFromInt(record.address); self.removePageOwner(record); self.backing_allocator.rawFree(ptr[0..record.backing_len], record.alignment, ret_addr); } fn releaseLiveLargeAllocations(self: *Self, ret_addr: usize) void { var iterator = self.live.valueIterator(); while (iterator.next()) |record| { if (record.kind == .large) self.releaseLarge(record.*, ret_addr); } } fn addChunk(self: *Self, class_index: usize, ret_addr: usize) !void { const class_state = &self.classes[class_index]; const block_size = size_class.size(class_index); const block_stride = self.blockStride(block_size); if (class_state.next_chunk_blocks == 0) { class_state.next_chunk_blocks = self.initialChunkBlocks(block_stride); } const capacity = class_state.next_chunk_blocks; const area_len = std.math.mul(usize, capacity, block_stride) catch return error.OutOfMemory; const alignment = Alignment.fromByteUnits(@max(block_stride, min_alignment)); const base = self.backing_allocator.rawAlloc(area_len, alignment, ret_addr) orelse return error.OutOfMemory; errdefer self.backing_allocator.rawFree(base[0..area_len], alignment, ret_addr); const chunk = try self.backing_allocator.create(Chunk); errdefer self.backing_allocator.destroy(chunk); const states = try self.backing_allocator.alloc(BlockState, capacity); errdefer self.backing_allocator.free(states); const requested_lens = try self.backing_allocator.alloc(usize, capacity); errdefer self.backing_allocator.free(requested_lens); const allocation_ids = try self.backing_allocator.alloc(u64, capacity); errdefer self.backing_allocator.free(allocation_ids); const allocation_return_addresses = try self.backing_allocator.alloc(usize, capacity); errdefer self.backing_allocator.free(allocation_return_addresses); const free_return_addresses = try self.backing_allocator.alloc(usize, capacity); errdefer self.backing_allocator.free(free_return_addresses); const repair_paddings = try self.backing_allocator.alloc(usize, capacity); errdefer self.backing_allocator.free(repair_paddings); const free_epochs = try self.backing_allocator.alloc(u64, capacity); errdefer self.backing_allocator.free(free_epochs); const free_quarantine_epochs = try self.backing_allocator.alloc(u64, capacity); errdefer self.backing_allocator.free(free_quarantine_epochs); const free_patterns = try self.backing_allocator.alloc(u64, capacity); errdefer self.backing_allocator.free(free_patterns); const free_issue_reported = try self.backing_allocator.alloc(bool, capacity); errdefer self.backing_allocator.free(free_issue_reported); @memset(states, .fresh); @memset(requested_lens, 0); @memset(repair_paddings, 0); @memset(allocation_ids, 0); @memset(allocation_return_addresses, 0); @memset(free_return_addresses, 0); @memset(free_epochs, 0); @memset(free_quarantine_epochs, 0); @memset(free_patterns, 0); @memset(free_issue_reported, false); self.fillFreedPattern(base, area_len, self.freshFreedPattern()); chunk.* = .{ .class_index = class_index, .block_size = block_size, .block_stride = block_stride, .capacity = capacity, .live_count = 0, .base = base, .area_len = area_len, .states = states, .requested_lens = requested_lens, .repair_paddings = repair_paddings, .allocation_ids = allocation_ids, .allocation_return_addresses = allocation_return_addresses, .free_return_addresses = free_return_addresses, .free_epochs = free_epochs, .free_quarantine_epochs = free_quarantine_epochs, .free_patterns = free_patterns, .free_issue_reported = free_issue_reported, }; try class_state.chunks.append(self.backing_allocator, chunk); class_state.capacity += capacity; class_state.next_chunk_blocks = std.math.mul(usize, capacity, 2) catch capacity; } fn destroyChunk(self: *Self, chunk: *Chunk) void { self.backing_allocator.rawFree( chunk.base[0..chunk.area_len], .fromByteUnits(@max(chunk.block_stride, min_alignment)), @returnAddress(), ); self.backing_allocator.free(chunk.states); self.backing_allocator.free(chunk.requested_lens); self.backing_allocator.free(chunk.repair_paddings); self.backing_allocator.free(chunk.allocation_ids); self.backing_allocator.free(chunk.allocation_return_addresses); self.backing_allocator.free(chunk.free_return_addresses); self.backing_allocator.free(chunk.free_epochs); self.backing_allocator.free(chunk.free_quarantine_epochs); self.backing_allocator.free(chunk.free_patterns); self.backing_allocator.free(chunk.free_issue_reported); self.backing_allocator.destroy(chunk); } fn blockStride(self: *Self, block_size: usize) usize { return switch (self.config.mode) { .diehard, .exterminator => block_size, .dieharder => if (block_size < page_size) page_size else block_size, }; } fn initialChunkBlocks(self: *Self, block_stride: usize) usize { const base = @max(self.config.min_chunk_blocks, 1); if (self.config.mode == .dieharder and block_stride >= page_size) return @max(@min(base, 16), 2); return base; } fn shouldGrow(self: *Self, class_state: *const ClassState) bool { if (class_state.capacity == 0) return true; return self.config.numerator * (class_state.live_count + 1) >= class_state.capacity * self.config.denominator; } fn blockByOrdinal(self: *Self, class_state: *ClassState, ordinal: usize) BlockRef { _ = self; var remaining = ordinal; for (class_state.chunks.items) |chunk| { if (remaining < chunk.capacity) return .{ .chunk = chunk, .index = remaining }; remaining -= chunk.capacity; } unreachable; } fn totalAllocationLen(self: *Self, requested_len: usize, repair_padding: usize) ?usize { const occupied_len = std.math.add(usize, @max(requested_len, 1), repair_padding) catch return null; return std.math.add(usize, occupied_len, self.config.diagnosticRedZoneBytes()) catch null; } fn installCanary(self: *Self, ptr: [*]u8, requested_len: usize, repair_padding: usize, block_size: usize) void { const red_zone = self.config.diagnosticRedZoneBytes(); const start = std.math.add(usize, @max(requested_len, 1), repair_padding) catch return; if (red_zone == 0 or start >= block_size) return; const canary_len = @min(red_zone, block_size - start); @memset(ptr[start .. start + canary_len], canary_byte); } fn checkCanary(self: *Self, record: *AllocationRecord, ret_addr: usize) bool { const red_zone = self.config.diagnosticRedZoneBytes(); const start = std.math.add(usize, @max(record.requested_len, 1), record.repair_padding) catch return false; if (red_zone == 0 or start >= record.block_size) return false; const canary_len = @min(red_zone, record.block_size - start); const ptr: [*]u8 = @ptrFromInt(record.address); var offset = start; while (offset < start + canary_len) : (offset += 1) { if (ptr[offset] != canary_byte) { if (!record.canary_issue_reported) { self.recordIssue(.{ .kind = .buffer_overflow, .address = record.address, .offset = offset, .requested_len = record.requested_len, .block_size = record.block_size, .allocation_id = record.allocation_id, .allocation_return_address = record.allocation_return_address, .free_return_address = record.free_return_address, .free_epoch = record.free_epoch, .return_address = ret_addr, }); record.canary_issue_reported = true; } return true; } } record.canary_issue_reported = false; return false; } fn scanLiveCanaries(self: *Self, ret_addr: usize) void { if (!self.diagnosticsActive()) return; var iterator = self.live.valueIterator(); while (iterator.next()) |record| _ = self.checkCanary(record, ret_addr); } fn scanFreedMemory(self: *Self, ret_addr: usize) void { if (!self.diagnosticsActive()) return; for (&self.classes) |*class_state| { for (class_state.chunks.items) |chunk| { for (chunk.states, 0..) |state, index| { if (state != .free or chunk.free_issue_reported[index]) continue; chunk.free_issue_reported[index] = self.checkFreedPattern( chunk.blockPtr(index), chunk.block_size, chunk.requested_lens[index], chunk.allocation_ids[index], chunk.allocation_return_addresses[index], chunk.free_return_addresses[index], chunk.free_epochs[index], chunk.free_patterns[index], ret_addr, ); } } } for (self.large_quarantine.items) |*record| { if (record.free_issue_reported) continue; const ptr: [*]u8 = @ptrFromInt(record.address); record.free_issue_reported = self.checkFreedPattern( ptr, record.block_size, record.requested_len, record.allocation_id, record.allocation_return_address, record.free_return_address, record.free_epoch, record.free_pattern, ret_addr, ); } } fn drainLargeQuarantine(self: *Self, ret_addr: usize) void { var index: usize = 0; while (index < self.large_quarantine.items.len) { var record = &self.large_quarantine.items[index]; if (!record.free_issue_reported) { const ptr: [*]u8 = @ptrFromInt(record.address); record.free_issue_reported = self.checkFreedPattern( ptr, record.block_size, record.requested_len, record.allocation_id, record.allocation_return_address, record.free_return_address, record.free_epoch, record.free_pattern, ret_addr, ); } if (self.epoch -% record.free_epoch < record.free_quarantine_epochs) { index += 1; continue; } const removed = self.large_quarantine.swapRemove(index); self.releaseLarge(removed, ret_addr); } } fn checkFreedPattern( self: *Self, ptr: [*]u8, block_size: usize, requested_len: usize, allocation_id: u64, allocation_return_address: usize, free_return_address: usize, free_epoch: u64, pattern: u64, ret_addr: usize, ) bool { var index: usize = 0; while (index < block_size) : (index += 1) { if (ptr[index] != patternByte(pattern, index)) { self.recordIssue(.{ .kind = .use_after_free, .address = @intFromPtr(ptr), .offset = index, .requested_len = requested_len, .block_size = block_size, .allocation_id = allocation_id, .allocation_return_address = allocation_return_address, .free_return_address = free_return_address, .free_epoch = free_epoch, .return_address = ret_addr, }); return true; } } return false; } fn freshFreedPattern(self: *Self) u64 { return switch (self.config.mode) { .dieharder => 0, .diehard, .exterminator => repeatedPattern(freed_byte), }; } fn nextFreedPattern(self: *Self) u64 { return switch (self.config.mode) { .dieharder => 0, .diehard, .exterminator => sanitizedFreedPattern(self.prng.random().int(u64)), }; } fn nextAllocationId(self: *Self) u64 { const id = self.next_allocation_id; self.next_allocation_id +%= 1; if (self.next_allocation_id == 0) self.next_allocation_id = 1; return id; } fn writeFreedPattern(self: *Self) bool { return switch (self.config.mode) { .diehard => self.diagnosticsActive(), .dieharder, .exterminator => true, }; } fn fillFreedPattern(self: *Self, ptr: [*]u8, len: usize, pattern: u64) void { _ = self; var index: usize = 0; while (index < len) : (index += 1) ptr[index] = patternByte(pattern, index); } fn recordUnknownFree(self: *Self, address: usize, len: usize, alignment: Alignment, ret_addr: usize) void { _ = alignment; if (self.known.get(address)) |record| { self.recordIssue(.{ .kind = .double_free, .address = address, .requested_len = len, .block_size = record.block_size, .allocation_id = record.allocation_id, .allocation_return_address = record.allocation_return_address, .free_return_address = record.free_return_address, .free_epoch = record.free_epoch, .return_address = ret_addr, }); return; } if (self.pageOwnedRecord(address)) |record| { self.recordIssue(.{ .kind = .invalid_free, .address = address, .offset = address - record.address, .requested_len = len, .block_size = record.block_size, .allocation_id = record.allocation_id, .allocation_return_address = record.allocation_return_address, .free_return_address = record.free_return_address, .free_epoch = record.free_epoch, .return_address = ret_addr, }); return; } if (self.containingKnownRecord(address)) |record| { self.recordIssue(.{ .kind = .invalid_free, .address = address, .offset = address - record.address, .requested_len = len, .block_size = record.block_size, .allocation_id = record.allocation_id, .allocation_return_address = record.allocation_return_address, .free_return_address = record.free_return_address, .free_epoch = record.free_epoch, .return_address = ret_addr, }); return; } self.recordIssue(.{ .kind = .invalid_free, .address = address, .requested_len = len, .return_address = ret_addr, }); } fn pageOwnedRecord(self: *Self, address: usize) ?AllocationRecord { if (!self.usesPageOwners()) return null; const owner_address = self.page_owners.get(pageNumber(address)) orelse return null; const record = self.known.get(owner_address) orelse return null; if (address <= record.address) return null; const end = std.math.add(usize, record.address, record.block_size) catch std.math.maxInt(usize); if (address >= end) return null; return record; } fn containingKnownRecord(self: *Self, address: usize) ?AllocationRecord { var iterator = self.known.valueIterator(); while (iterator.next()) |record| { if (address <= record.address) continue; const end = std.math.add(usize, record.address, record.block_size) catch std.math.maxInt(usize); if (address < end) return record.*; } return null; } fn ensurePageOwnerCapacity(self: *Self, record: AllocationRecord) !void { return self.ensurePageOwnerCapacityFor(record.address, record.block_size); } fn ensurePageOwnerCapacityFor(self: *Self, address: usize, block_size: usize) !void { if (!self.usesPageOwners()) return; const pages = std.math.cast(u32, pageSpan(address, block_size)) orelse return error.OutOfMemory; try self.page_owners.ensureUnusedCapacity(pages); } fn putPageOwnerAssumeCapacity(self: *Self, record: AllocationRecord) void { if (!self.usesPageOwners()) return; const first_page = pageNumber(record.address); const pages = pageSpan(record.address, record.block_size); var index: usize = 0; while (index < pages) : (index += 1) { self.page_owners.putAssumeCapacity(first_page + index, record.address); } } fn removePageOwner(self: *Self, record: AllocationRecord) void { if (!self.usesPageOwners()) return; const first_page = pageNumber(record.address); const pages = pageSpan(record.address, record.block_size); var index: usize = 0; while (index < pages) : (index += 1) { _ = self.page_owners.remove(first_page + index); } } fn usesPageOwners(self: *const Self) bool { return self.config.mode == .dieharder; } fn recordIssue(self: *Self, issue: Issue) void { if (!self.diagnosticsActive()) return; self.counters.increment(issue.kind); self.last_issue = issue; self.issues.append(issue); } fn diagnosticsActive(self: *const Self) bool { return self.config.diagnostics.enabled or self.config.mode == .exterminator; } fn lock(self: *Self) void { if (!self.config.thread_safe) return; while (!self.mutex.tryLock()) std.atomic.spinLoopHint(); } fn unlock(self: *Self) void { if (self.config.thread_safe) self.mutex.unlock(); }};Source: lib/deadalloc/src/root.zig:46
zig
pub const DeadAllocator = allocator_mod.DeadAllocator;Complete caller list for DeadAllocator.allocator
25 direct callers.
lib.deadalloc.src.allocator.test_deinit_releases_reported_large_leaks[function] — test source atlib/deadalloc/src/allocator.zig:1660in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_freed_patterns_detect_fixed_fill_byte_writes[function] — test source atlib/deadalloc/src/allocator.zig:1556in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_invalid_free_reports_interior_allocation_context[function] — test source atlib/deadalloc/src/allocator.zig:1413in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_raw_remap_rejects_freed_allocation[function] — test source atlib/deadalloc/src/allocator.zig:1450in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_raw_remap_rejects_unknown_allocation[function] — test source atlib/deadalloc/src/allocator.zig:1436in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_live_red_zone_overflow_once[function] — test source atlib/deadalloc/src/allocator.zig:1585in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_stale_large_writes_while_quarantined[function] — test source atlib/deadalloc/src/allocator.zig:1603in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_stale_small_writes_before_reuse[function] — test source atlib/deadalloc/src/allocator.zig:1516in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_includes_bounded_leak_issues[function] — test source atlib/deadalloc/src/allocator.zig:1493in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_retains_structured_issue_history[function] — test source atlib/deadalloc/src/allocator.zig:1465in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_scans_entire_freed_small_block[function] — test source atlib/deadalloc/src/allocator.zig:1534in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_resize_checks_existing_red_zone_before_updating_size[function] — test source atlib/deadalloc/src/allocator.zig:1572in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diehard_mode_returns_aligned_disjoint_allocations[function] — test source atlib/deadalloc/src/allocator.zig:1104in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_large_allocations_are_page_granular[function] — test source atlib/deadalloc/src/allocator.zig:1138in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_mode_delays_reuse_and_detects_stale_writes_when_diagnostics_are_enabled[function] — test source atlib/deadalloc/src/allocator.zig:1673in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_exterminator_mode_reports_invalid_free_double_free_overflow_and_leaks[function] — test source atlib/deadalloc/src/allocator.zig:1389in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_thread-safe_allocator_supports_concurrent_allocation_and_cross-thread_free[function] — test source atlib/deadalloc/src/allocator.zig:1757in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.properties.allocator.AlignmentProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:301in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.AllocatorStateProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:74in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.DiagnosticFaultProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:158in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.DiagnosticHistoryProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:439in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.InteriorFreeProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:359in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.LargeAllocationProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:339in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.LeakIssueProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:471in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.RawRemapProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:391in nearest public ownerlib.deadalloc.src.properties.allocator
Complete caller list for DeadAllocator.deinit
34 direct callers.
lib.deadalloc.src.allocator.test_deinit_releases_reported_large_leaks[function] — test source atlib/deadalloc/src/allocator.zig:1660in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_freed_patterns_detect_fixed_fill_byte_writes[function] — test source atlib/deadalloc/src/allocator.zig:1556in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_invalid_free_reports_interior_allocation_context[function] — test source atlib/deadalloc/src/allocator.zig:1413in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_raw_remap_rejects_freed_allocation[function] — test source atlib/deadalloc/src/allocator.zig:1450in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_raw_remap_rejects_unknown_allocation[function] — test source atlib/deadalloc/src/allocator.zig:1436in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_live_red_zone_overflow_once[function] — test source atlib/deadalloc/src/allocator.zig:1585in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_stale_large_writes_while_quarantined[function] — test source atlib/deadalloc/src/allocator.zig:1603in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_stale_small_writes_before_reuse[function] — test source atlib/deadalloc/src/allocator.zig:1516in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_includes_bounded_leak_issues[function] — test source atlib/deadalloc/src/allocator.zig:1493in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_retains_structured_issue_history[function] — test source atlib/deadalloc/src/allocator.zig:1465in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_scans_entire_freed_small_block[function] — test source atlib/deadalloc/src/allocator.zig:1534in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_resize_checks_existing_red_zone_before_updating_size[function] — test source atlib/deadalloc/src/allocator.zig:1572in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diehard_mode_preserves_freed_small_contents_until_reuse[function] — test source atlib/deadalloc/src/allocator.zig:1622in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diehard_mode_returns_aligned_disjoint_allocations[function] — test source atlib/deadalloc/src/allocator.zig:1104in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_large_allocations_are_page_granular[function] — test source atlib/deadalloc/src/allocator.zig:1138in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_mode_delays_reuse_and_detects_stale_writes_when_diagnostics_are_enabled[function] — test source atlib/deadalloc/src/allocator.zig:1673in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_mode_zeroes_freed_small_contents[function] — test source atlib/deadalloc/src/allocator.zig:1641in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_page_owners_cover_large_quarantined_pages[function] — test source atlib/deadalloc/src/allocator.zig:1185in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_page_owners_resolve_interior_small_frees[function] — test source atlib/deadalloc/src/allocator.zig:1158in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_releases_large_page_owners_when_quarantine_append_fails[function] — test source atlib/deadalloc/src/allocator.zig:1260in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_exterminator_mode_reports_invalid_free_double_free_overflow_and_leaks[function] — test source atlib/deadalloc/src/allocator.zig:1389in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_random_small_block_probes_tolerate_occupied_collisions[function] — test source atlib/deadalloc/src/allocator.zig:1118in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_repair_config_applies_dangle_extension_by_allocation_and_free_site[function] — test source atlib/deadalloc/src/allocator.zig:1355in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_repair_config_applies_overflow_padding_by_allocation_site[function] — test source atlib/deadalloc/src/allocator.zig:1324in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_small_quarantine_availability_survives_epoch_wraparound[function] — test source atlib/deadalloc/src/allocator.zig:1286in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_thread-safe_allocator_supports_concurrent_allocation_and_cross-thread_free[function] — test source atlib/deadalloc/src/allocator.zig:1757in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.properties.allocator.AlignmentProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:301in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.AllocatorStateProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:74in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.DiagnosticFaultProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:158in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.DiagnosticHistoryProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:439in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.InteriorFreeProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:359in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.LargeAllocationProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:339in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.LeakIssueProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:471in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.RawRemapProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:391in nearest public ownerlib.deadalloc.src.properties.allocator
Complete caller list for DeadAllocator.init
34 direct callers.
lib.deadalloc.src.allocator.test_deinit_releases_reported_large_leaks[function] — test source atlib/deadalloc/src/allocator.zig:1660in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_freed_patterns_detect_fixed_fill_byte_writes[function] — test source atlib/deadalloc/src/allocator.zig:1556in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_invalid_free_reports_interior_allocation_context[function] — test source atlib/deadalloc/src/allocator.zig:1413in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_raw_remap_rejects_freed_allocation[function] — test source atlib/deadalloc/src/allocator.zig:1450in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_raw_remap_rejects_unknown_allocation[function] — test source atlib/deadalloc/src/allocator.zig:1436in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_live_red_zone_overflow_once[function] — test source atlib/deadalloc/src/allocator.zig:1585in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_stale_large_writes_while_quarantined[function] — test source atlib/deadalloc/src/allocator.zig:1603in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_stale_small_writes_before_reuse[function] — test source atlib/deadalloc/src/allocator.zig:1516in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_includes_bounded_leak_issues[function] — test source atlib/deadalloc/src/allocator.zig:1493in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_retains_structured_issue_history[function] — test source atlib/deadalloc/src/allocator.zig:1465in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_scans_entire_freed_small_block[function] — test source atlib/deadalloc/src/allocator.zig:1534in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_resize_checks_existing_red_zone_before_updating_size[function] — test source atlib/deadalloc/src/allocator.zig:1572in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diehard_mode_preserves_freed_small_contents_until_reuse[function] — test source atlib/deadalloc/src/allocator.zig:1622in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diehard_mode_returns_aligned_disjoint_allocations[function] — test source atlib/deadalloc/src/allocator.zig:1104in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_large_allocations_are_page_granular[function] — test source atlib/deadalloc/src/allocator.zig:1138in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_mode_delays_reuse_and_detects_stale_writes_when_diagnostics_are_enabled[function] — test source atlib/deadalloc/src/allocator.zig:1673in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_mode_zeroes_freed_small_contents[function] — test source atlib/deadalloc/src/allocator.zig:1641in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_page_owners_cover_large_quarantined_pages[function] — test source atlib/deadalloc/src/allocator.zig:1185in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_page_owners_resolve_interior_small_frees[function] — test source atlib/deadalloc/src/allocator.zig:1158in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_releases_large_page_owners_when_quarantine_append_fails[function] — test source atlib/deadalloc/src/allocator.zig:1260in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_exterminator_mode_reports_invalid_free_double_free_overflow_and_leaks[function] — test source atlib/deadalloc/src/allocator.zig:1389in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_random_small_block_probes_tolerate_occupied_collisions[function] — test source atlib/deadalloc/src/allocator.zig:1118in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_repair_config_applies_dangle_extension_by_allocation_and_free_site[function] — test source atlib/deadalloc/src/allocator.zig:1355in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_repair_config_applies_overflow_padding_by_allocation_site[function] — test source atlib/deadalloc/src/allocator.zig:1324in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_small_quarantine_availability_survives_epoch_wraparound[function] — test source atlib/deadalloc/src/allocator.zig:1286in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_thread-safe_allocator_supports_concurrent_allocation_and_cross-thread_free[function] — test source atlib/deadalloc/src/allocator.zig:1757in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.properties.allocator.AlignmentProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:301in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.AllocatorStateProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:74in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.DiagnosticFaultProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:158in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.DiagnosticHistoryProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:439in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.InteriorFreeProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:359in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.LargeAllocationProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:339in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.LeakIssueProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:471in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.RawRemapProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:391in nearest public ownerlib.deadalloc.src.properties.allocator
Complete caller list for DeadAllocator.rawAlloc
10 direct callers.
tiny.deadalloc.DeadAllocator.rawRemap[method] atlib/deadalloc/src/allocator.zig:316lib.deadalloc.src.allocator.rawAlloc[function] — private source atlib/deadalloc/src/allocator.zig:1084in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diehard_mode_preserves_freed_small_contents_until_reuse[function] — test source atlib/deadalloc/src/allocator.zig:1622in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_mode_zeroes_freed_small_contents[function] — test source atlib/deadalloc/src/allocator.zig:1641in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_page_owners_cover_large_quarantined_pages[function] — test source atlib/deadalloc/src/allocator.zig:1185in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_page_owners_resolve_interior_small_frees[function] — test source atlib/deadalloc/src/allocator.zig:1158in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_releases_large_page_owners_when_quarantine_append_fails[function] — test source atlib/deadalloc/src/allocator.zig:1260in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_repair_config_applies_dangle_extension_by_allocation_and_free_site[function] — test source atlib/deadalloc/src/allocator.zig:1355in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_repair_config_applies_overflow_padding_by_allocation_site[function] — test source atlib/deadalloc/src/allocator.zig:1324in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_small_quarantine_availability_survives_epoch_wraparound[function] — test source atlib/deadalloc/src/allocator.zig:1286in nearest public ownerlib.deadalloc.src.allocator
Complete call list for DeadAllocator.rawAlloc
7 direct calls.
lib.deadalloc.src.allocator.Config.repairPadding[method] — private source atlib/deadalloc/src/allocator.zig:67in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.allocateLarge[method] — private source atlib/deadalloc/src/allocator.zig:493in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.allocateSmall[method] — private source atlib/deadalloc/src/allocator.zig:369in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.drainLargeQuarantine[method] — private source atlib/deadalloc/src/allocator.zig:804in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.lock[method] — private source atlib/deadalloc/src/allocator.zig:1017in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.totalAllocationLen[method] — private source atlib/deadalloc/src/allocator.zig:717in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.unlock[method] — private source atlib/deadalloc/src/allocator.zig:1022in nearest public ownerlib.deadalloc.src.allocator
Complete caller list for DeadAllocator.rawFree
10 direct callers.
tiny.deadalloc.DeadAllocator.rawRemap[method] atlib/deadalloc/src/allocator.zig:316lib.deadalloc.src.allocator.rawFree[function] — private source atlib/deadalloc/src/allocator.zig:1099in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diehard_mode_preserves_freed_small_contents_until_reuse[function] — test source atlib/deadalloc/src/allocator.zig:1622in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_mode_zeroes_freed_small_contents[function] — test source atlib/deadalloc/src/allocator.zig:1641in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_page_owners_cover_large_quarantined_pages[function] — test source atlib/deadalloc/src/allocator.zig:1185in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_page_owners_resolve_interior_small_frees[function] — test source atlib/deadalloc/src/allocator.zig:1158in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_releases_large_page_owners_when_quarantine_append_fails[function] — test source atlib/deadalloc/src/allocator.zig:1260in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_repair_config_applies_dangle_extension_by_allocation_and_free_site[function] — test source atlib/deadalloc/src/allocator.zig:1355in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_repair_config_applies_overflow_padding_by_allocation_site[function] — test source atlib/deadalloc/src/allocator.zig:1324in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_small_quarantine_availability_survives_epoch_wraparound[function] — test source atlib/deadalloc/src/allocator.zig:1286in nearest public ownerlib.deadalloc.src.allocator
Complete call list for DeadAllocator.rawFree
7 direct calls.
lib.deadalloc.src.allocator.DeadAllocator.checkCanary[method] — private source atlib/deadalloc/src/allocator.zig:730in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.freeLarge[method] — private source atlib/deadalloc/src/allocator.zig:563in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.freeSmall[method] — private source atlib/deadalloc/src/allocator.zig:543in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.lock[method] — private source atlib/deadalloc/src/allocator.zig:1017in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.recordIssue[method] — private source atlib/deadalloc/src/allocator.zig:1006in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.recordUnknownFree[method] — private source atlib/deadalloc/src/allocator.zig:898in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.unlock[method] — private source atlib/deadalloc/src/allocator.zig:1022in nearest public ownerlib.deadalloc.src.allocator
Complete call list for DeadAllocator.rawResize
8 direct calls.
lib.deadalloc.src.allocator.DeadAllocator.checkCanary[method] — private source atlib/deadalloc/src/allocator.zig:730in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.drainLargeQuarantine[method] — private source atlib/deadalloc/src/allocator.zig:804in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.installCanary[method] — private source atlib/deadalloc/src/allocator.zig:722in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.lock[method] — private source atlib/deadalloc/src/allocator.zig:1017in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.recordIssue[method] — private source atlib/deadalloc/src/allocator.zig:1006in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.recordUnknownFree[method] — private source atlib/deadalloc/src/allocator.zig:898in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.totalAllocationLen[method] — private source atlib/deadalloc/src/allocator.zig:717in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.DeadAllocator.unlock[method] — private source atlib/deadalloc/src/allocator.zig:1022in nearest public ownerlib.deadalloc.src.allocator
Complete caller list for DeadAllocator.report
27 direct callers.
lib.deadalloc.src.allocator.test_deinit_releases_reported_large_leaks[function] — test source atlib/deadalloc/src/allocator.zig:1660in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_freed_patterns_detect_fixed_fill_byte_writes[function] — test source atlib/deadalloc/src/allocator.zig:1556in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_invalid_free_reports_interior_allocation_context[function] — test source atlib/deadalloc/src/allocator.zig:1413in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_raw_remap_rejects_freed_allocation[function] — test source atlib/deadalloc/src/allocator.zig:1450in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_raw_remap_rejects_unknown_allocation[function] — test source atlib/deadalloc/src/allocator.zig:1436in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_live_red_zone_overflow_once[function] — test source atlib/deadalloc/src/allocator.zig:1585in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_stale_large_writes_while_quarantined[function] — test source atlib/deadalloc/src/allocator.zig:1603in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_detects_stale_small_writes_before_reuse[function] — test source atlib/deadalloc/src/allocator.zig:1516in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_includes_bounded_leak_issues[function] — test source atlib/deadalloc/src/allocator.zig:1493in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_retains_structured_issue_history[function] — test source atlib/deadalloc/src/allocator.zig:1465in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_report_scans_entire_freed_small_block[function] — test source atlib/deadalloc/src/allocator.zig:1534in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diagnostic_resize_checks_existing_red_zone_before_updating_size[function] — test source atlib/deadalloc/src/allocator.zig:1572in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_diehard_mode_preserves_freed_small_contents_until_reuse[function] — test source atlib/deadalloc/src/allocator.zig:1622in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_mode_delays_reuse_and_detects_stale_writes_when_diagnostics_are_enabled[function] — test source atlib/deadalloc/src/allocator.zig:1673in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_mode_zeroes_freed_small_contents[function] — test source atlib/deadalloc/src/allocator.zig:1641in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_page_owners_cover_large_quarantined_pages[function] — test source atlib/deadalloc/src/allocator.zig:1185in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_dieharder_page_owners_resolve_interior_small_frees[function] — test source atlib/deadalloc/src/allocator.zig:1158in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_exterminator_mode_reports_invalid_free_double_free_overflow_and_leaks[function] — test source atlib/deadalloc/src/allocator.zig:1389in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_repair_config_applies_overflow_padding_by_allocation_site[function] — test source atlib/deadalloc/src/allocator.zig:1324in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.allocator.test_thread-safe_allocator_supports_concurrent_allocation_and_cross-thread_free[function] — test source atlib/deadalloc/src/allocator.zig:1757in nearest public ownerlib.deadalloc.src.allocatorlib.deadalloc.src.properties.allocator.AllocatorStateProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:74in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.DiagnosticFaultProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:158in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.DiagnosticHistoryProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:439in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.InteriorFreeProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:359in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.LargeAllocationProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:339in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.LeakIssueProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:471in nearest public ownerlib.deadalloc.src.properties.allocatorlib.deadalloc.src.properties.allocator.RawRemapProperty.property[function] — private source atlib/deadalloc/src/properties/allocator.zig:391in nearest public ownerlib.deadalloc.src.properties.allocator
Audit
| Definitions | 9 |
|---|---|
| Public names | 9 |
| Members | 14 |
| Version | 26.7.0 |
| Revision | daab053ee433 |