Ler Stack Traces em Zig — Interpretar Rastros de Execução
Stack traces são a ferramenta principal para diagnosticar crashes e erros em Zig. Aprender a lê-los corretamente acelera drasticamente o debugging. Este guia ensina a interpretar cada parte de um stack trace.
Anatomia de um Stack Trace
Quando um panic ocorre em modo Debug, Zig gera um stack trace como este:
thread 28435 panic: index out of bounds
/home/user/projeto/src/parser.zig:142:25: 0x1064ab3 in parse (parser)
const token = tokens[pos];
^~~~~~~~~
/home/user/projeto/src/main.zig:58:9: 0x1063f21 in processar (main)
try parser.parse(dados);
^~~~~~~~~~~~~~~~~~~
/home/user/projeto/src/main.zig:23:5: 0x1063c10 in main (main)
try processar(entrada);
^~~~~~~~~~~~~~~~~~~~~~
Lendo de Cima para Baixo
Linha 1: Tipo do panic
thread 28435 panic: index out of bounds- Qual thread, qual tipo de erro
Linha 2-3: Local exato do erro
/home/user/projeto/src/parser.zig:142:25= arquivo:linha:coluna0x1064ab3= endereço de memória da instruçãoin parse (parser)= nome da função e do módulo- A seta
^~~~~~~~~aponta exatamente para a expressão problemática
Linhas seguintes: Cadeia de chamadas
- Quem chamou a função onde o erro ocorreu
- De baixo para cima: main -> processar -> parse
Tipos Comuns de Panic
index out of bounds
panic: index out of bounds
Tentou acessar um índice fora do array/slice. Olhe o tamanho do array e o índice usado.
integer overflow
panic: integer overflow
Operação aritmética excedeu o range do tipo. Verifique os valores e considere tipo maior ou wrapping arithmetic.
reached unreachable code
panic: reached unreachable code
Execução atingiu um unreachable. O switch/if não cobriu todos os casos.
attempt to unwrap null
panic: attempt to cast away optionality on null value
Usou .? em um optional que era null. Use orelse ou if para verificar.
attempt to use null pointer
panic: attempt to use null value
Dereferenciou um ponteiro null. Verifique se o ponteiro é válido antes de usar.
Stack Trace sem Símbolos
Em modo Release, o stack trace pode mostrar apenas endereços:
0x1064ab3 in ??? (???)
0x1063f21 in ??? (???)
0x1063c10 in ??? (???)
Soluções:
# 1. Recompilar em Debug para obter stack trace completo
zig build # Debug mode padrão
# 2. Usar addr2line para traduzir endereços
addr2line -e zig-out/bin/meu-app 0x1064ab3
# 3. Em ReleaseSafe, stack traces ainda são disponíveis
zig build -Doptimize=ReleaseSafe # Mantém informações de debug
Stack Trace em Testes
Test [3/5] test "processar dados"... FAIL
/home/user/projeto/src/lib.zig:89:15: 0x20a3b1 in test "processar dados"
try expect(resultado == 42);
^~~~~~~~~~~~~~~~~
error: 'test "processar dados"' failed
Em testes, o stack trace mostra qual asserção falhou e em qual linha. Use std.testing.expectEqual para mensagens mais descritivas.
Stack Trace com Threads
thread 28436 panic: index out of bounds
O número da thread ajuda a identificar qual thread teve o problema. Para debugging multi-thread:
// Identifique threads com prints
fn worker(id: usize) void {
std.debug.print("Thread {d} iniciando\n", .{id});
// ...
}
Usando GDB/LLDB com Stack Traces
# GDB
gdb ./zig-out/bin/meu-app
(gdb) run
# Quando crashar:
(gdb) bt # backtrace completo
(gdb) bt full # backtrace com variáveis locais
(gdb) frame 2 # ir para frame específico
(gdb) print var # imprimir variável
(gdb) info locals # ver todas as variáveis locais
# LLDB (macOS)
lldb ./zig-out/bin/meu-app
(lldb) run
(lldb) bt
(lldb) frame select 2
(lldb) p variavel
Capturando Stack Traces Programaticamente
const std = @import("std");
fn registrar_stack_trace() void {
const trace = @returnAddress();
std.debug.print("Chamado de: 0x{x}\n", .{trace});
}
// Para debug mais detalhado
fn debug_aqui() void {
var buf: [4096]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buf);
const allocator = fba.allocator();
_ = allocator;
const debug_info = std.debug.getSelfDebugInfo() catch return;
_ = debug_info;
// Usar para resolver endereços para nomes de funções
}
Dicas de Leitura Rápida
- Olhe a primeira linha — Tipo do panic (index, overflow, null, etc.)
- Olhe a segunda linha — Arquivo e linha exatos do erro
- Olhe a seta — Aponta para a expressão exata que falhou
- Leia de cima para baixo — Do erro até main, para entender o fluxo
- Compile em Debug — Sempre debug com modo Debug para máxima informação
Quando o Stack Trace Não Ajuda
Se o stack trace não é suficiente:
// Adicione prints estratégicos antes do crash
std.debug.print("ANTES: pos={d}, tokens.len={d}\n", .{ pos, tokens.len });
// Use breakpoints com GDB
// (gdb) break src/parser.zig:140
// (gdb) run
// Use @breakpoint() no código para parar o debugger
@breakpoint();
Veja Também
- Crash em Runtime — Tipos de crashes
- Debugar Segfaults — Segmentation faults
- Memory Leak — Leaks com stack trace
- Zig Não Compila — Erros de compilação
- Erros do Compilador — Referência de erros