GeneralPurposeAllocator does have support for detecting double frees:
but it needs the GeneralPurposeAllocator.Config
to have retain_metadata = true
and never_unmap = true
:
Test code:
const std = @import("std");
test "double free" {
var gpa = std.heap.GeneralPurposeAllocator(.{
.safety = true,
.never_unmap = true,
.retain_metadata = true,
}){};
defer std.debug.assert(gpa.deinit() == .ok);
const allocator = gpa.allocator();
const alloc = try allocator.alloc(u8, 8);
allocator.free(alloc);
allocator.free(alloc);
}
For me on Windows this is outputting:
[gpa] (err): Double free detected. Allocation:
First free:
Second free:
C:\Users\Ryan\Programming\Zig\tmp\doublefree.zig:10:19: 0x7510f5 in test.double free (test.exe.obj)
allocator.free(alloc);
^
C:\Users\Ryan\Programming\Zig\zig\lib\compiler\test_runner.zig:158:25: 0x75bc1a in mainTerminal (test.exe.obj)
if (test_fn.func()) |_| {
^
C:\Users\Ryan\Programming\Zig\zig\lib\compiler\test_runner.zig:35:28: 0x751998 in main (test.exe.obj)
return mainTerminal();
^
C:\Users\Ryan\Programming\Zig\zig\lib\std\start.zig:350:53: 0x751713 in WinStartup (test.exe.obj)
std.os.windows.ntdll.RtlExitUserProcess(callMain());
^
???:?:?: 0x7ff91a157343 in ??? (KERNEL32.DLL)
???:?:?: 0x7ff91c0e26b0 in ??? (ntdll.dll)
unsure if the first free stack trace being empty is a Windows-only bug or a general regression.
(note: it looks like I may have accidentally regressed retain_metadata
in GeneralPurposeAllocator: Considerably improve worst case performance by squeek502 · Pull Request #17383 · ziglang/zig · GitHub; if there are two allocations of 8 bytes in the above test, it hits an assertion failure during gpa.deinit()
)