I’m using Zig 0.15.2.
I assumed that calling DebugAllocator.deinit frees all memory in it (independent from all the leak checking stuff). That doesn’t seem to be the case though or am I misunderstanding this somehow? Here is my snippet:
pub fn main() !void {
const allocator_type: enum { debug, arena } = .debug;
var outer: std.heap.DebugAllocator(.{}) = .{};
var inner = switch (allocator_type) {
.debug => std.heap.DebugAllocator(.{ .safety = false }){ .backing_allocator = outer.allocator() },
.arena => std.heap.ArenaAllocator.init(outer.allocator()),
};
_ = try inner.allocator().alloc(i64, 100);
_ = inner.deinit();
_ = outer.deinit();
}
Since the inner allocator has safety = false, I expected this to run through without any output. The call to outer.deinit reports a leak though. And that’s after I called inner.deinit. Just to prove that I didn’t miss something very obvious, I added the switch to use an arena as a drop-in replacement of inner. That works so it must be in the DebugAllocator. I didn’t dig very deep yet, but the code of deinit looks good enough to me.
pub fn deinit(self: *Self) std.heap.Check {
const leaks = if (config.safety) self.detectLeaks() else false;
if (config.retain_metadata) self.freeRetainedMetadata();
self.large_allocations.deinit(self.backing_allocator);
self.* = undefined;
return if (leaks) .leak else .ok;
}