summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-24 13:12:45 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commitc3688203847b66870c83c3c0b4d26c51c58e34c3 (patch)
tree82d4684ada6225505c6a03093ca21f1292437e12 /src
parenta4f5e5b8fc5aed894f13ffe2b96cbd9c5a11770d (diff)
downloadpardes-c3688203847b66870c83c3c0b4d26c51c58e34c3.tar.gz
pardes-c3688203847b66870c83c3c0b4d26c51c58e34c3.zip
Check each subsystem's memory under one DebugAllocator, not two
In a Debug build memory.zig put each subsystem allocator (core, frame, lsp, tree-sitter, image, PDF) under a DebugAllocator of its own, which is what reports that subsystem's leaks and makes memory.deinit panic on one. Beneath it, past the fixed buffer, was the allocator the shell passed in: init.gpa, which std.process.Init already makes a DebugAllocator in Debug. Every block that spilled out of a fixed buffer was tracked, checked and given stack traces twice, and in a test both layers sat on std.testing.allocator. A Debug build now puts the page allocator beneath the subsystem DebugAllocators, so each allocation passes through exactly one. The shells' own gpa is still std.process.Init's DebugAllocator for everything else, and a release build is unchanged: the subsystems sit on the gpa, no DebugAllocator anywhere. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/memory.zig18
1 files changed, 12 insertions, 6 deletions
diff --git a/src/memory.zig b/src/memory.zig
index e5394b4f..a2c5547c 100644
--- a/src/memory.zig
+++ b/src/memory.zig
@@ -101,20 +101,26 @@ var pdf_debug: Debug = .init;
// One session at a time; free its allocations before deinit. Concurrent LSP workers use the caller's allocator.
pub fn init(fallback: Allocator) Allocators {
- pardes_fallback.fallback_allocator = fallback;
- frame_fallback.fallback_allocator = fallback;
+ // A Debug build puts each allocator under a DebugAllocator of its own,
+ // which reports that subsystem's leaks and bad frees (deinit panics on a
+ // leak). Beneath that goes the page allocator rather than `fallback`: in
+ // a Debug build `fallback` is std.process.Init's gpa, a DebugAllocator
+ // already, and a second one checked every block twice.
+ const backing = if (debug_enabled) std.heap.page_allocator else fallback;
+ pardes_fallback.fallback_allocator = backing;
+ frame_fallback.fallback_allocator = backing;
frame_fallback.get_called = if (std.debug.runtime_safety) false else {};
- tree_sitter_fallback.fallback_allocator = fallback;
+ tree_sitter_fallback.fallback_allocator = backing;
tree_sitter_fallback.get_called = if (std.debug.runtime_safety) false else {};
- image_fallback.fallback_allocator = fallback;
+ image_fallback.fallback_allocator = backing;
image_fallback.get_called = if (std.debug.runtime_safety) false else {};
- pdf_fallback.fallback_allocator = fallback;
+ pdf_fallback.fallback_allocator = backing;
pdf_fallback.get_called = if (std.debug.runtime_safety) false else {};
const raw: Allocators = .{
.pardes = pardes_fallback.get(),
.frame = frame_fallback.get(),
- .lsp = fallback,
+ .lsp = backing,
.tree_sitter = tree_sitter_fallback.get(),
.image = image_fallback.get(),
.pdf = pdf_fallback.get(),