Zig Crash em Runtime — Identificar e Corrigir

Zig Crash em Runtime — Identificar e Corrigir

Crashes em runtime no Zig são geralmente detectáveis e fornecem informações detalhadas em modo Debug. Este guia ajuda a identificar as causas mais comuns e como corrigi-las.

Tipos de Crashes

1. Panic: “index out of bounds”

Causa: Acessar um índice fora dos limites de um array ou slice.

const arr = [_]i32{ 1, 2, 3 };
// const x = arr[5]; // PANIC: index out of bounds

// SOLUÇÃO: Verificar limites
if (indice < arr.len) {
    const x = arr[indice];
    _ = x;
}

2. Panic: “reached unreachable code”

Causa: Execução atingiu um ponto marcado como unreachable.

const valor: u8 = switch (x) {
    0 => "zero",
    1 => "um",
    else => unreachable, // PANIC se x não for 0 ou 1
};

// SOLUÇÃO: Tratar todos os casos ou usar else
const valor: u8 = switch (x) {
    0 => "zero",
    1 => "um",
    else => "outro",
};

3. Panic: “integer overflow”

Causa: Operação aritmética excede o range (apenas em Debug mode).

var x: u8 = 255;
// x += 1; // PANIC: integer overflow

// SOLUÇÃO 1: Usar tipo maior
var x: u16 = 255;
x += 1; // OK: 256

// SOLUÇÃO 2: Wrapping
var y: u8 = 255;
y +%= 1; // 0, sem panic

// SOLUÇÃO 3: Verificar antes
if (x < 255) x += 1;

4. Panic: “attempt to unwrap null”

Causa: Usar .? em um optional que é null.

const maybe: ?i32 = null;
// const x = maybe.?; // PANIC!

// SOLUÇÃO: Verificar antes
const x = maybe orelse {
    std.debug.print("Valor era null!\n", .{});
    return;
};

5. Stack Overflow

Causa: Recursão muito profunda ou alocação grande na stack.

// PROBLEMA: Recursão infinita
fn recursiva(n: usize) usize {
    return recursiva(n + 1); // stack overflow
}

// SOLUÇÃO: Caso base
fn recursiva(n: usize) usize {
    if (n >= 1000) return n;
    return recursiva(n + 1);
}

// PROBLEMA: Array grande na stack
// var buffer: [100_000_000]u8 = undefined; // stack overflow!

// SOLUÇÃO: Alocar no heap
const buffer = try allocator.alloc(u8, 100_000_000);
defer allocator.free(buffer);

Como Depurar

1. Compilar em modo Debug

# Modo debug (padrão) — máxima informação
zig build

# NUNCA depurar com ReleaseFast — remove verificações
# zig build -Doptimize=ReleaseFast  # NÃO para debug

2. Ler o Stack Trace

thread 12345 panic: index out of bounds
src/main.zig:42:15: 0x204a3b in processar (main)
    const valor = dados[indice];
                       ^
src/main.zig:28:5: 0x204912 in main (main)
    try processar(meus_dados);
    ^
  • Linha 1: Tipo do panic
  • Linha 2-3: Arquivo, linha e coluna exatos
  • Linha 4-5: Quem chamou a função

3. Usar std.debug.print

fn processar(dados: []const u8, indice: usize) void {
    std.debug.print("dados.len={d}, indice={d}\n", .{ dados.len, indice });
    // Agora você vê os valores antes do crash
    const valor = dados[indice];
    _ = valor;
}

4. Usar GDB/LLDB

# Compilar com informações de debug
zig build

# Usar GDB
gdb ./zig-out/bin/meu-app
(gdb) run
(gdb) backtrace  # ver stack trace
(gdb) print variavel  # inspecionar valores

# Usar LLDB (macOS)
lldb ./zig-out/bin/meu-app
(lldb) run
(lldb) bt  # backtrace

Veja Também

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.