authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-24 13:31:29-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-26 19:58:56-08:00
logb243e8f8cc7ee27dfa7318d1c3698d01582e84ae
treef4e80f83869b42e0a2f1624019f53c238f3a8df3
parenta72c411fdbafc206115c4f9eb19216d504c36a31

std: integrate DebugAllocator with terminal mode

by adding a new std.Option for log.terminalMode this is an alternative to the approach that was deleted in aa57793b680b3da05f1d888b4df15807905e57c8

3 files changed, 68 insertions(+), 14 deletions(-)

lib/std/heap/debug_allocator.zig+58-14
......@@ -84,7 +84,7 @@ const builtin = @import("builtin");
8484const StackTrace = std.builtin.StackTrace;
8585
8686const std = @import("std");
87const log = std.log.scoped(.gpa);
87const log = std.log.scoped(.DebugAllocator);
8888const math = std.math;
8989const assert = std.debug.assert;
9090const mem = std.mem;
......@@ -441,7 +441,11 @@ pub fn DebugAllocator(comptime config: Config) type {
441441 const page_addr = @intFromPtr(bucket) & ~(page_size - 1);
442442 const addr = page_addr + slot_index * size_class;
443443 log.err("memory address 0x{x} leaked: {f}", .{
444 addr, std.debug.FormatStackTrace{ .stack_trace = stack_trace },
444 addr,
445 std.debug.FormatStackTrace{
446 .stack_trace = stack_trace,
447 .terminal_mode = std.log.terminalMode(),
448 },
445449 });
446450 leaks += 1;
447451 }
......@@ -471,7 +475,10 @@ pub fn DebugAllocator(comptime config: Config) type {
471475 const stack_trace = large_alloc.getStackTrace(.alloc);
472476 log.err("memory address 0x{x} leaked: {f}", .{
473477 @intFromPtr(large_alloc.bytes.ptr),
474 std.debug.FormatStackTrace{ .stack_trace = stack_trace },
478 std.debug.FormatStackTrace{
479 .stack_trace = stack_trace,
480 .terminal_mode = std.log.terminalMode(),
481 },
475482 });
476483 leaks += 1;
477484 }
......@@ -528,9 +535,18 @@ pub fn DebugAllocator(comptime config: Config) type {
528535 var addr_buf: [stack_n]usize = undefined;
529536 const second_free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf);
530537 log.err("Double free detected. Allocation: {f} First free: {f} Second free: {f}", .{
531 std.debug.FormatStackTrace{ .stack_trace = alloc_stack_trace },
532 std.debug.FormatStackTrace{ .stack_trace = free_stack_trace },
533 std.debug.FormatStackTrace{ .stack_trace = second_free_stack_trace },
538 std.debug.FormatStackTrace{
539 .stack_trace = alloc_stack_trace,
540 .terminal_mode = std.log.terminalMode(),
541 },
542 std.debug.FormatStackTrace{
543 .stack_trace = free_stack_trace,
544 .terminal_mode = std.log.terminalMode(),
545 },
546 std.debug.FormatStackTrace{
547 .stack_trace = second_free_stack_trace,
548 .terminal_mode = std.log.terminalMode(),
549 },
534550 });
535551 }
536552
......@@ -575,8 +591,14 @@ pub fn DebugAllocator(comptime config: Config) type {
575591 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
576592 entry.value_ptr.bytes.len,
577593 old_mem.len,
578 std.debug.FormatStackTrace{ .stack_trace = entry.value_ptr.getStackTrace(.alloc) },
579 std.debug.FormatStackTrace{ .stack_trace = free_stack_trace },
594 std.debug.FormatStackTrace{
595 .stack_trace = entry.value_ptr.getStackTrace(.alloc),
596 .terminal_mode = std.log.terminalMode(),
597 },
598 std.debug.FormatStackTrace{
599 .stack_trace = free_stack_trace,
600 .terminal_mode = std.log.terminalMode(),
601 },
580602 });
581603 }
582604
......@@ -682,8 +704,14 @@ pub fn DebugAllocator(comptime config: Config) type {
682704 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
683705 entry.value_ptr.bytes.len,
684706 old_mem.len,
685 std.debug.FormatStackTrace{ .stack_trace = entry.value_ptr.getStackTrace(.alloc) },
686 std.debug.FormatStackTrace{ .stack_trace = free_stack_trace },
707 std.debug.FormatStackTrace{
708 .stack_trace = entry.value_ptr.getStackTrace(.alloc),
709 .terminal_mode = std.log.terminalMode(),
710 },
711 std.debug.FormatStackTrace{
712 .stack_trace = free_stack_trace,
713 .terminal_mode = std.log.terminalMode(),
714 },
687715 });
688716 }
689717
......@@ -910,8 +938,12 @@ pub fn DebugAllocator(comptime config: Config) type {
910938 old_memory.len,
911939 std.debug.FormatStackTrace{
912940 .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc),
941 .terminal_mode = std.log.terminalMode(),
942 },
943 std.debug.FormatStackTrace{
944 .stack_trace = free_stack_trace,
945 .terminal_mode = std.log.terminalMode(),
913946 },
914 std.debug.FormatStackTrace{ .stack_trace = free_stack_trace },
915947 });
916948 }
917949 if (alignment != slot_alignment) {
......@@ -921,8 +953,12 @@ pub fn DebugAllocator(comptime config: Config) type {
921953 alignment.toByteUnits(),
922954 std.debug.FormatStackTrace{
923955 .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc),
956 .terminal_mode = std.log.terminalMode(),
957 },
958 std.debug.FormatStackTrace{
959 .stack_trace = free_stack_trace,
960 .terminal_mode = std.log.terminalMode(),
924961 },
925 std.debug.FormatStackTrace{ .stack_trace = free_stack_trace },
926962 });
927963 }
928964 }
......@@ -1011,8 +1047,12 @@ pub fn DebugAllocator(comptime config: Config) type {
10111047 memory.len,
10121048 std.debug.FormatStackTrace{
10131049 .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc),
1050 .terminal_mode = std.log.terminalMode(),
1051 },
1052 std.debug.FormatStackTrace{
1053 .stack_trace = free_stack_trace,
1054 .terminal_mode = std.log.terminalMode(),
10141055 },
1015 std.debug.FormatStackTrace{ .stack_trace = free_stack_trace },
10161056 });
10171057 }
10181058 if (alignment != slot_alignment) {
......@@ -1022,8 +1062,12 @@ pub fn DebugAllocator(comptime config: Config) type {
10221062 alignment.toByteUnits(),
10231063 std.debug.FormatStackTrace{
10241064 .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc),
1065 .terminal_mode = std.log.terminalMode(),
1066 },
1067 std.debug.FormatStackTrace{
1068 .stack_trace = free_stack_trace,
1069 .terminal_mode = std.log.terminalMode(),
10251070 },
1026 std.debug.FormatStackTrace{ .stack_trace = free_stack_trace },
10271071 });
10281072 }
10291073 }
lib/std/log.zig+8
......@@ -80,6 +80,14 @@ pub fn logEnabled(comptime level: Level, comptime scope: @EnumLiteral()) bool {
8080 return @intFromEnum(level) <= @intFromEnum(std.options.log_level);
8181}
8282
83pub const terminalMode = std.options.logTerminalMode;
84
85pub fn defaultTerminalMode() std.Io.Terminal.Mode {
86 const stderr = std.debug.lockStderr(&.{}).terminal();
87 std.debug.unlockStderr();
88 return stderr.mode;
89}
90
8391/// The default implementation for the log function. Custom log functions may
8492/// forward log messages to this function.
8593///
lib/std/std.zig+2
......@@ -129,6 +129,8 @@ pub const Options = struct {
129129 args: anytype,
130130 ) void = log.defaultLog,
131131
132 logTerminalMode: fn () Io.Terminal.Mode = log.defaultTerminalMode,
133
132134 /// Overrides `std.heap.page_size_min`.
133135 page_size_min: ?usize = null,
134136 /// Overrides `std.heap.page_size_max`.