Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

writeCurrentStackTrace

debug.writeCurrentStackTrace
pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Terminal) Writer.Error!void

File

lib/std/debug.zig:718

Code

pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Terminal) Writer.Error!void {
    const writer = t.writer;

    var text_arena: std.heap.ArenaAllocator = .init(getDebugInfoAllocator());
    defer text_arena.deinit();

    if (!std.options.allow_stack_tracing) {
        t.setColor(.dim) catch {};
        try writer.print("Cannot print stack trace: stack tracing is disabled\n", .{});
        t.setColor(.reset) catch {};
        return;
    }
    const di = getSelfDebugInfo() catch |err| switch (err) {
        error.UnsupportedTarget => {
            t.setColor(.dim) catch {};
            try writer.print("Cannot print stack trace: debug info unavailable for target\n", .{});
            t.setColor(.reset) catch {};
            return;
        },
    };
    var it: StackIterator = .init(options.context);
    defer it.deinit();
    if (!it.stratOk(options.allow_unsafe_unwind)) {
        t.setColor(.dim) catch {};
        try writer.print("Cannot print stack trace: safe unwind unavailable for target\n", .{});
        t.setColor(.reset) catch {};
        return;
    }
    var total_frames: usize = 0;
    var wait_for = options.first_address;
    var printed_any_frame = false;
    const io = std.Options.debug_io;
    while (true) switch (it.next(io)) {
        .switch_to_fp => |unwind_error| {
            switch (StackIterator.fp_usability) {
                .useless, .unsafe => {},
                .safe, .ideal => continue, // no need to even warn
            }
            const module_name = di.getModuleName(io, unwind_error.address) catch "???";
            const caption: []const u8 = switch (unwind_error.err) {
                error.MissingDebugInfo => "unwind info unavailable",
                error.InvalidDebugInfo => "unwind info invalid",
                error.UnsupportedDebugInfo => "unwind info unsupported",
                error.ReadFailed => "filesystem error",
                error.OutOfMemory => "out of memory",
                error.Canceled => "operation canceled",
                error.Unexpected => "unexpected error",
            };
            if (it.stratOk(options.allow_unsafe_unwind)) {
                t.setColor(.dim) catch {};
                try writer.print(
                    "Unwind error at address `{s}:0x{x}` ({s}), remaining frames may be incorrect\n",
                    .{ module_name, unwind_error.address, caption },
                );
                t.setColor(.reset) catch {};
            } else {
                t.setColor(.dim) catch {};
                try writer.print(
                    "Unwind error at address `{s}:0x{x}` ({s}), stopping trace early\n",
                    .{ module_name, unwind_error.address, caption },
                );
                t.setColor(.reset) catch {};
                return;
            }
        },
        .end => break,
        .frame => |ret_addr| {
            if (total_frames > 10_000) {
                t.setColor(.dim) catch {};
                try writer.print(
                    "Stopping trace after {d} frames (large frame count may indicate broken debug info)\n",
                    .{total_frames},
                );
                t.setColor(.reset) catch {};
                return;
            }
            total_frames += 1;
            if (wait_for) |target| {
                if (ret_addr != target) continue;
                wait_for = null;
            }
            // `ret_addr` is the return address, which is *after* the function call.
            // Subtract 1 to get an address *in* the function call for a better source location.
            try printSourceAtAddress(io, &text_arena, di, t, .{
                .address = ret_addr -| StackIterator.ra_call_offset,
                .resolve_inline_callers = true,
            });
            printed_any_frame = true;
        },
    };
    if (!printed_any_frame) return writer.writeAll("(empty stack trace)\n");
}