authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-01 18:10:24-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-04 00:27:08-08:00
log50e185b71822c180fccd07826a8dd5e3ec641cc1
treea3672f8f94fd038c55155ea141432c926907f802
parent0362d9f3215e36dd12b5ba47bca8a9cd107b1697

start: tweak allocator choice

Favor DebugAllocator in Debug mode, even when linking libc. Prevent use of smp_allocator when single_threaded

2 files changed, 13 insertions(+), 21 deletions(-)

lib/std/process/Environ.zig-14
......@@ -381,20 +381,6 @@ pub fn createMap(env: Environ, allocator: Allocator) CreateMapError!Map {
381381 try result.put(key, value);
382382 }
383383 return result;
384 } else if (builtin.link_libc) {
385 var ptr = env.block;
386 while (ptr[0]) |line| : (ptr += 1) {
387 var line_i: usize = 0;
388 while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {}
389 const key = line[0..line_i];
390
391 var end_i: usize = line_i;
392 while (line[end_i] != 0) : (end_i += 1) {}
393 const value = line[line_i + 1 .. end_i];
394
395 try result.put(key, value);
396 }
397 return result;
398384 } else {
399385 for (env.block) |opt_line| {
400386 const line = opt_line.?;
lib/std/start.zig+13-7
......@@ -623,7 +623,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [:null]?[*:0]u8)
623623 return callMain(argv[0..argc], envp);
624624}
625625
626fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) callconv(.c) c_int {
626fn main(c_argc: c_int, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.c) c_int {
627627 var env_count: usize = 0;
628628 while (c_envp[env_count] != null) : (env_count += 1) {}
629629 const envp = c_envp[0..env_count :null];
......@@ -638,7 +638,7 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal
638638 return callMainWithArgs(@as(usize, @intCast(c_argc)), @as([*][*:0]u8, @ptrCast(c_argv)), envp);
639639}
640640
641fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int {
641fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]u8) callconv(.c) c_int {
642642 const argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@intCast(c_argc)];
643643 if (@sizeOf(std.Io.Threaded.Argv0) != 0) {
644644 if (std.Options.debug_threaded_io) |t| t.argv0.value = argv[0];
......@@ -649,7 +649,11 @@ fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int {
649649/// General error message for a malformed return type
650650const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";
651651
652const use_debug_allocator = !builtin.link_libc and !native_arch.isWasm() and builtin.mode == .Debug;
652const use_debug_allocator = !native_arch.isWasm() and switch (builtin.mode) {
653 .Debug => true,
654 .ReleaseSafe => !builtin.link_libc, // Not ideal, but the best we have for now.
655 .ReleaseFast, .ReleaseSmall => !builtin.link_libc and builtin.single_threaded, // Also not ideal.
656};
653657var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
654658
655659inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.Block) u8 {
......@@ -660,14 +664,16 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B
660664 .environ = .{ .block = environ },
661665 }));
662666
663 const gpa = if (builtin.link_libc)
664 std.heap.c_allocator
665 else if (native_arch.isWasm())
667 const gpa = if (native_arch.isWasm())
666668 std.heap.wasm_allocator
667669 else if (use_debug_allocator)
668670 debug_allocator.allocator()
671 else if (builtin.link_libc)
672 std.heap.c_allocator
673 else if (!builtin.single_threaded)
674 std.heap.smp_allocator
669675 else
670 std.heap.smp_allocator;
676 comptime unreachable;
671677
672678 defer if (use_debug_allocator) {
673679 _ = debug_allocator.deinit(); // Leaks do not affect return code.