---
title: "Debugging em Zig: Técnicas e Ferramentas Completas"
url: "https://ziglang.com.br/tutoriais/zig-debugging/"
markdown_url: "https://ziglang.com.br/tutoriais/zig-debugging.MD"
description: "Guia completo de debugging em Zig. Aprenda a usar GDB, LLDB, std.debug, técnicas de print debugging, depuração de memória e integração com VS Code."
date: "2026-02-10"
author: ""
---

# Debugging em Zig: Técnicas e Ferramentas Completas

Guia completo de debugging em Zig. Aprenda a usar GDB, LLDB, std.debug, técnicas de print debugging, depuração de memória e integração com VS Code.


Debugar código é uma habilidade essencial para qualquer desenvolvedor. No Zig, você tem acesso a ferramentas poderosas para identificar e corrigir bugs — desde técnicas simples de print debugging até debuggers profissionais como GDB e LLDB.

Neste tutorial completo, você vai aprender todas as técnicas de debugging disponíveis no Zig: como usar o `std.debug` para diagnósticos rápidos, depurar com GDB/LLDB, analisar stack traces, debugar problemas de memória e integrar tudo com seu IDE favorito.

> **Pré-requisito:** Conhecimento básico de Zig. Se você está começando, confira nosso [Guia para Iniciantes](/tutoriais/zig-para-iniciantes/).

## Visão Geral do Debugging em Zig

### Filosofia do Zig: Debugabilidade

O Zig foi projetado com debugabilidade em mente:

1. **Stack traces limpas** — Sem overhead de runtime pesado
2. **Modo Debug seguro** — Checks de segurança ativados por padrão
3. **Sem malloc escondido** — Você controla toda alocação
4. **Erros explícitos** — Error types ao invés de exceções
5. **Comportamento definido** — Undefined behavior é detectado em Debug

### Modos de Build e Debugging

| Modo | Uso | Debug | Performance |
|---|---|---|---|
| `Debug` | Desenvolvimento | ✅ Stack traces, bounds checks | Lento |
| `ReleaseSafe` | Produção com segurança | ✅ Safety checks | Rápido |
| `ReleaseFast` | Máxima velocidade | ❌ Sem checks | Máximo |
| `ReleaseSmall` | Binários pequenos | ❌ Sem checks | Rápido |

> 💡 **Dica:** Sempre desenvolva no modo `Debug` para ter acesso completo a informações de debugging.

```bash
# Build com símbolos de debug (padrão)
zig build

# Build de release (sem símbolos de debug)
zig build -Doptimize=ReleaseFast
```

### Ferramentas de Debugging Disponíveis

```
┌─────────────────────────────────────────────────────────────┐
│                    Debugging em Zig                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Rápido e Simples        Debugger Profissional              │
│  ┌──────────────┐        ┌──────────────┐                   │
│  │ std.debug    │        │ GDB          │                   │
│  │ print        │        │ LLDB         │                   │
│  │ dumpStackTrace│       │ VS Code      │                   │
│  │ assert       │        │ Breakpoints  │                   │
│  └──────────────┘        └──────────────┘                   │
│                                                             │
│  Análise de Memória                                         │
│  ┌──────────────┐                                           │
│  │ GeneralPurposeAllocator│                                  │
│  │ GPA.detectLeaks()      │                                  │
│  │ Valgrind (Linux)       │                                  │
│  └──────────────┘                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

## Print Debugging com std.debug

A forma mais rápida de debugar é usar `std.debug.print`. É simples, mas poderosa.

### Básico: std.debug.print

```zig
const std = @import("std");

pub fn main() void {
    const valor = 42;
    
    // Print básico
    std.debug.print("Valor: {d}\n", .{valor});
    
    // Múltiplos valores
    const nome = "Zig";
    const versao = 0.15;
    std.debug.print("{s} v{d}\n", .{nome, versao});
    
    // Debug format (mostra estrutura completa)
    const ponto = .{ .x = 10, .y = 20 };
    std.debug.print("Ponto: {any}\n", .{ponto});
    // Saída: Ponto: struct{comptime x: comptime_int = 10, comptime y: comptime_int = 20}
}
```

### Formatos de Print Úteis

```zig
const std = @import("std");

pub fn main() void {
    const num: i32 = 42;
    const hex: u32 = 0xDEADBEEF;
    const ptr: *i32 = @ptrFromInt(0x1000);
    const bin: u8 = 0b10101010;
    
    // Diferentes formatos
    std.debug.print("Decimal: {d}\n", .{num});      // 42
    std.debug.print("Hexadecimal: {x}\n", .{hex});  // deadbeef
    std.debug.print("Hex uppercase: {X}\n", .{hex});// DEADBEEF
    std.debug.print("Ponteiro: {*p}\n", .{ptr});    // 0x1000
    std.debug.print("Binário: {b}\n", .{bin});      // 10101010
    std.debug.print("Caractere: {c}\n", .{'A'});    // A
    std.debug.print("String: {s}\n", .{"hello"});   // hello
    std.debug.print("Any: {any}\n", .{num});        // 42
}
```

### Asserts e Verificações

Asserts são essenciais para capturar bugs cedo:

```zig
const std = @import("std");

fn dividir(a: i32, b: i32) i32 {
    // Assert básico
    std.debug.assert(b != 0);  // Panic se b == 0
    
    return @divTrunc(a, b);
}

fn buscar(array: []const i32, indice: usize) i32 {
    // Assert com mensagem customizada
    std.debug.assert(indice < array.len);
    
    return array[indice];
}

// Asserts em tempo de compilação
comptime {
    std.debug.assert(@sizeOf(usize) >= @sizeOf(u32));
}
```

### Dump de Stack Trace

Quando algo dá errado, veja onde:

```zig
const std = @import("std");

fn funcaoNivel3() void {
    std.debug.print("Em funcaoNivel3\n", .{});
    
    // Imprime stack trace atual
    const trace = @import("builtin").StackTrace;
    std.debug.dumpStackTrace(trace{});
}

fn funcaoNivel2() void {
    funcaoNivel3();
}

fn funcaoNivel1() void {
    funcaoNivel2();
}

pub fn main() void {
    funcaoNivel1();
}
```

Saída típica:

```
Em funcaoNivel3
first render trace:
/home/user/projeto/src/main.zig:6:31: 0x1033b60 in funcaoNivel3 (main)
/home/user/projeto/src/main.zig:13:18: 0x1033b80 in funcaoNivel2 (main)
/home/user/projeto/src/main.zig:17:18: 0x1033ba0 in funcaoNivel1 (main)
/home/user/projeto/src/main.zig:21:17: 0x1033bc0 in main (main)
```

### Print Condicional

Use comptime para prints de debug opcionais:

```zig
const std = @import("std");
const builtin = @import("builtin");

const debug_mode = builtin.mode == .Debug;

fn debugPrint(comptime fmt: []const u8, args: anytype) void {
    if (debug_mode) {
        std.debug.print("[DEBUG] " ++ fmt ++ "\n", args);
    }
}

pub fn main() void {
    debugPrint("Iniciando aplicação", .{});
    debugPrint("Config carregada: {any}", .{.{
        .host = "localhost",
        .port = 8080,
    }});
}
```

## Debugging com GDB

GDB (GNU Debugger) é o debugger padrão para Linux. Funciona perfeitamente com código Zig.

### Preparação: Build com Símbolos de Debug

```bash
# Build padrão já inclui símbolos
zig build

# Ou explicitamente
zig build-exe -ODebug src/main.zig

# Para C/C++ mixed projects
zig build -Doptimize=Debug
```

### Comandos Básicos do GDB

```bash
# Iniciar GDB
gdb ./zig-out/bin/meu-programa

# Ou com arguments
gdb --args ./zig-out/bin/meu-programa arg1 arg2
```

**Comandos essenciais:**

| Comando | Abreviação | Descrição |
|---|---|---|
| `run` | `r` | Iniciar execução |
| `break` | `b` | Definir breakpoint |
| `continue` | `c` | Continuar execução |
| `step` | `s` | Entrar na função |
| `next` | `n` | Próxima linha (pula função) |
| `finish` | `fin` | Terminar função atual |
| `print` | `p` | Imprimir valor |
| `backtrace` | `bt` | Stack trace |
| `info locals` | | Variáveis locais |
| `quit` | `q` | Sair |

### Exemplo Prático com GDB

**Código:**

```zig
const std = @import("std");

fn fatorial(n: u32) u32 {
    if (n <= 1) return 1;
    return n * fatorial(n - 1);
}

pub fn main() void {
    const n = 5;
    const resultado = fatorial(n);
    std.debug.print("{d}! = {d}\n", .{n, resultado});
}
```

**Sessão GDB:**

```bash
# Build
zig build-exe -ODebug src/main.zig -o debug_app

# Iniciar GDB
gdb ./debug_app

# Dentro do GDB:
(gdb) break fatorial           # Breakpoint na função
Breakpoint 1 at 0x2370

(gdb) run                      # Executar
Starting program: /home/user/debug_app
Breakpoint 1, fatorial (n=5) at src/main.zig:4
4           if (n <= 1) return 1;

(gdb) print n                  # Inspecionar valor
$1 = 5

(gdb) continue                 # Continuar
Continuing.
Breakpoint 1, fatorial (n=4) at src/main.zig:4
4           if (n <= 1) return 1;

(gdb) bt                       # Stack trace
#0  fatorial (n=4) at src/main.zig:4
#1  0x0000555555556379 in fatorial (n=5) at src/main.zig:6
#2  0x000055555555639e in main () at src/main.zig:11

(gdb) continue                 # Continuar até o fim
Continuing.
5! = 120
[Inferior 1 (process 12345) exited normally]

(gdb) quit
```

### Breakpoints Condicionais

```bash
# Breakpoint apenas quando n == 0
(gdb) break fatorial if n == 0

# Breakpoint na linha 6 apenas quando n > 10
(gdb) break src/main.zig:6 if n > 10

# Breakpoint temporário (para na primeira vez)
(gdb) tbreak fatorial
```

### Watchpoints

Monitore quando uma variável muda:

```bash
# Parar quando resultado mudar
(gdb) watch resultado

# Parar quando a memória em um endereço mudar
(gdb) watch *(int*)0x7fffffffe000
```

### Inspecionando Structs

```zig
const Pessoa = struct {
    nome: []const u8,
    idade: u32,
    ativo: bool,
};

const p = Pessoa{
    .nome = "Maria",
    .idade = 30,
    .ativo = true,
};
```

```bash
(gdb) print p
$1 = {
  nome = {
    ptr = 0x555555556004 "Maria",
    len = 5
  },
  idade = 30,
  ativo = true
}

(gdb) print p.idade
$2 = 30

(gdb) print p.nome.ptr
$3 = (const u8 *) 0x555555556004 "Maria"
```

## Debugging com LLDB

LLDB é o debugger padrão no macOS e parte do LLVM. Também funciona no Linux.

### Comandos LLDB vs GDB

| GDB | LLDB | Descrição |
|---|---|---|
| `break` | `breakpoint set` ou `b` | Definir breakpoint |
| `run` | `run` ou `r` | Executar |
| `continue` | `continue` ou `c` | Continuar |
| `step` | `step` ou `s` | Entrar função |
| `next` | `next` ou `n` | Próxima linha |
| `print` | `expr` ou `p` | Imprimir valor |
| `backtrace` | `thread backtrace` ou `bt` | Stack trace |
| `info locals` | `frame variable` | Variáveis locais |
| `quit` | `quit` ou `q` | Sair |

### Sessão LLDB Exemplo

```bash
# Iniciar LLDB
lldb ./zig-out/bin/meu-programa

# Sessão:
(lldb) breakpoint set --name fatorial
Breakpoint 1: where = debug_app`fatorial + 4 at main.zig:4, address = 0x00002370

(lldb) run
Process 12345 launched
Process 12345 stopped
* thread #1, name = 'debug_app', stop reason = breakpoint 1.1
    frame #0: 0x0000555555556370 debug_app`fatorial(n=5) at main.zig:4
   1    const std = @import("std");
   2
   3    fn fatorial(n: u32) u32 {
-> 4        if (n <= 1) return 1;
   5        return n * fatorial(n - 1);
   6    }

(lldb) expr n
(unsigned int) $0 = 5

(lldb) thread backtrace
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x100003720 debug_app`fatorial(n=5) at main.zig:4
    frame #1: 0x100003784 debug_app`main at main.zig:11
    frame #2: 0x100003d54 debug_app`start + 52

(lldb) continue
Process 12345 resuming
5! = 120
Process 12345 exited with status = 0
```

## Stack Traces em Zig

### Obtendo Stack Traces

Zig torna fácil obter informações de onde seu código está:

```zig
const std = @import("std");

fn funcaoC() void {
    std.debug.print("Em funcaoC\n", .{});
    
    // Capturar stack trace
    var address_buffer: [10]usize = undefined;
    const trace = std.debug.StackTrace{
        .instruction_addresses = &address_buffer,
        .index = 0,
    };
    
    // Em caso de erro, você pode capturar o trace
    @panic("Erro intencional para demonstração");
}

fn funcaoB() void {
    funcaoC();
}

fn funcaoA() void {
    funcaoB();
}

pub fn main() void {
    funcaoA();
}
```

### Stack Trace de Erros

```zig
const std = @import("std");

fn podeFalhar() !void {
    return error.ErroExemplo;
}

pub fn main() !void {
    podeFalhar() catch |err| {
        std.debug.print("Erro capturado: {s}\n", .{@errorName(err)});
        
        // Em modo Debug, você tem stack trace automático
        if (@errorReturnTrace()) |trace| {
            std.debug.dumpStackTrace(trace.*);
        }
        
        return err;
    };
}
```

Saída em modo Debug:

```
Erro capturado: ErroExemplo
/home/user/projeto/src/main.zig:5:5: 0x1032a0 in podeFalhar (main)
    return error.ErroExemplo;
    ^
/home/user/projeto/src/main.zig:10:5: 0x1032f0 in main (main)
    podeFalhar() catch |err| {
    ^
```

## Debugging de Memória

### GeneralPurposeAllocator (GPA)

O `GeneralPurposeAllocator` é seu aliado para detectar problemas de memória:

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{
        .safety = true,        // Detecta use-after-free, double-free
        .thread_safety = true, // Thread-safe
    }){};
    defer {
        const deinit_status = gpa.deinit();
        if (deinit_status == .leak) {
            std.debug.print("⚠️  Memory leak detectado!\n", .{});
        }
    }
    
    const allocator = gpa.allocator();
    
    // Alocação
    const ptr = try allocator.alloc(u8, 100);
    defer allocator.free(ptr);
    
    // Se você esquecer o free, o GPA detecta no deinit
}
```

### Detectando Memory Leaks

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();
    
    // ❌ Memory leak - esquecemos de liberar
    const leaky = try allocator.alloc(u8, 100);
    _ = leaky;  // Nunca usamos free
    
    // O deinit vai detectar
    const status = gpa.deinit();
    if (status == .leak) {
        std.log.err("Memory leak detectado!", .{});
    }
}
```

Saída:

```
error(gpa): memory address 0x7f3a4c000b90 leaked:
/home/user/projeto/src/main.zig:8:40: 0x103450 in main (main)
    const leaky = try allocator.alloc(u8, 100);
                                       ^
```

### Detectando Use-After-Free

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    
    var ptr = try allocator.alloc(u8, 10);
    allocator.free(ptr);
    
    // ❌ Use-after-free - o GPA detecta
    ptr[0] = 42;  // Panic aqui!
}
```

Saída:

```
thread 12345 panic: Use of uninitialized memory
/home/user/projeto/src/main.zig:11:5: 0x1034a0 in main (main)
    ptr[0] = 42;
    ^
```

### Detectando Double-Free

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    
    const ptr = try allocator.alloc(u8, 10);
    allocator.free(ptr);
    
    // ❌ Double-free - o GPA detecta
    allocator.free(ptr);  // Panic aqui!
}
```

### Page Allocator para Valgrind

Para debugging avançado com Valgrind:

```zig
const std = @import("std");

pub fn main() !void {
    // PageAllocator é compatível com Valgrind
    var pa = std.heap.page_allocator;
    
    const ptr = try pa.alloc(u8, 4096);
    defer pa.free(ptr);
    
    // Use valgrind para detectar problemas
    // valgrind --leak-check=full ./meu-programa
}
```

## Integração com VS Code

### Configuração do Launch.json

Crie `.vscode/launch.json`:

```json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug Zig",
            "type": "lldb",
            "request": "launch",
            "program": "${workspaceFolder}/zig-out/bin/${input:program}",
            "args": [],
            "cwd": "${workspaceFolder}",
            "preLaunchTask": "build"
        }
    ],
    "inputs": [
        {
            "id": "program",
            "type": "pickString",
            "description": "Qual programa debugar?",
            "options": ["meu-programa"],
            "default": "meu-programa"
        }
    ]
}
```

### Configuração de Build Tasks

`.vscode/tasks.json`:

```json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "zig build",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "presentation": {
                "echo": true,
                "reveal": "always",
                "focus": false,
                "panel": "shared"
            },
            "problemMatcher": ["$gcc"]
        },
        {
            "label": "test",
            "type": "shell",
            "command": "zig build test",
            "group": "test"
        }
    ]
}
```

### Extensão Zig para VS Code

Instale a extensão oficial:

1. Abra VS Code
2. Ctrl+Shift+X (extensões)
3. Procure "Zig"
4. Instale "Zig" (ziglang.org)

**Features:**
- Syntax highlighting
- Autocomplete
- Go to definition
- Format on save (`zig fmt`)
- Build tasks integradas

### Breakpoints no VS Code

1. Clique na margem esquerda para adicionar breakpoint (ponto vermelho)
2. Pressione F5 para iniciar debugging
3. Use F10 (step over), F11 (step into), Shift+F11 (step out)
4. Variables panel mostra valores das variáveis
5. Watch panel para monitorar expressões

## Debugging de Erros Comuns

### Erro: "attempt to use null value"

```zig
const std = @import("std");

pub fn main() void {
    var ptr: ?*i32 = null;
    
    // ❌ Erro: tentando dereferenciar null
    ptr.?.* = 42;  // Panic: attempt to use null value
}
```

**Debug:**
```zig
// ✅ Verifique antes de usar
if (ptr) |p| {
    p.* = 42;
} else {
    std.debug.print("ptr é null!\n", .{});
}
```

### Erro: "index out of bounds"

```zig
const std = @import("std");

pub fn main() void {
    const array = [5]i32{1, 2, 3, 4, 5};
    const indice = 10;
    
    // ❌ Erro: índice fora dos limites
    const valor = array[indice];  // Panic aqui
}
```

**Debug:**
```zig
// ✅ Verifique bounds
std.debug.assert(indice < array.len);
const valor = array[indice];
```

### Erro: "integer overflow"

```zig
const std = @import("std");

pub fn main() void {
    var x: u8 = 255;
    
    // ❌ Erro: overflow em modo Debug
    x += 1;  // Panic: integer overflow
}
```

**Debug:**
```zig
// ✅ Use funções saturadas ou checked
const y = std.math.add(u8, x, 1) catch |err| {
    std.debug.print("Overflow! err={}\n", .{err});
    return;
};

// Ou use wrapping se for intencional
x = @addWithOverflow(x, 1)[0];
```

### Erro: "unreachable"

```zig
const std = @import("std");

fn parseNumero(input: []const u8) !i32 {
    if (input.len == 0) return error.Vazio;
    
    // ❌ Se chegar aqui com input inesperado
    unreachable;  // Panic!
}

pub fn main() !void {
    try parseNumero("abc");
}
```

**Debug:**
```zig
fn parseNumero(input: []const u8) !i32 {
    if (input.len == 0) return error.Vazio;
    if (std.mem.eql(u8, input, "abc")) return error.Invalido;
    
    // Agora unreachable é válido
    unreachable;
}
```

## Técnicas Avançadas de Debug

### Custom Panic Handler

```zig
const std = @import("std");

pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
    std.debug.print("\n╔════════════════════════════════════╗\n", .{});
    std.debug.print("║         PANIC DETECTADO!           ║\n", .{});
    std.debug.print("╚════════════════════════════════════╝\n", .{});
    std.debug.print("Mensagem: {s}\n", .{msg});
    
    if (error_return_trace) |trace| {
        std.debug.print("\nStack trace:\n", .{});
        std.debug.dumpStackTrace(trace.*);
    }
    
    std.process.exit(1);
}

pub fn main() void {
    @panic("Erro de demonstração");
}
```

### Logging Estruturado

```zig
const std = @import("std");

const LogLevel = enum {
    debug,
    info,
    warn,
    err,
};

fn log(comptime level: LogLevel, comptime fmt: []const u8, args: anytype) void {
    const prefix = switch (level) {
        .debug => "[DEBUG]",
        .info => "[INFO]",
        .warn => "[WARN]",
        .err => "[ERROR]",
    };
    
    std.debug.print(prefix ++ " " ++ fmt ++ "\n", args);
}

pub fn main() void {
    log(.info, "Aplicação iniciada", .{});
    log(.debug, "Configuração carregada: {any}", .{{ .port = 8080 }});
    log(.warn, "Conexão lenta detectada", .{});
}
```

### Time-based Debugging

```zig
const std = @import("std");

var timer: std.time.Timer = undefined;

fn startTimer() void {
    timer = std.time.Timer.start() catch unreachable;
}

fn logElapsed(comptime msg: []const u8) void {
    const elapsed_ns = timer.read();
    const elapsed_ms = @as(f64, @floatFromInt(elapsed_ns)) / 1_000_000.0;
    std.debug.print("[TIME] {s}: {d:.2}ms\n", .{msg, elapsed_ms});
}

pub fn main() !void {
    startTimer();
    
    // Código a ser medido
    var sum: u64 = 0;
    for (0..1_000_000) |i| {
        sum += i;
    }
    
    logElapsed("Loop de 1M iterações");
    std.debug.print("Soma: {d}\n", .{sum});
}
```

## Checklist de Debugging

### Quando seu código não funciona:

- [ ] **Build em modo Debug** — `zig build` (não ReleaseFast)
- [ ] **Adicione prints estratégicos** — Antes e depois de operações suspeitas
- [ ] **Verifique inputs** — Print todos os argumentos recebidos
- [ ] **Use asserts** — Verifique pré-condições e pós-condições
- [ ] **Verifique erros** — Todos os `try` e `catch` estão corretos?
- [ ] **Use GPA** — Detecte memory leaks automaticamente
- [ ] **Leia stack traces** — A última linha é onde o erro ocorreu
- [ ] **Debugger** — GDB/LLDB para investigação profunda

### Comandos Úteis:

```bash
# Build com informações de debug
zig build

# Run com diagnósticos
zig build run

# Testes
zig build test

# GDB
gdb ./zig-out/bin/meu-programa

# LLDB
lldb ./zig-out/bin/meu-programa

# Valgrind (Linux)
valgrind --leak-check=full ./zig-out/bin/meu-programa

# Strace (system calls)
strace ./zig-out/bin/meu-programa
```

## Resumo

| Situação | Ferramenta/Técnica |
|---|---|
| Debug rápido | `std.debug.print` |
| Stack trace | `std.debug.dumpStackTrace` |
| Verificações | `std.debug.assert` |
| Memory leaks | `GeneralPurposeAllocator` |
| Debug profundo | GDB ou LLDB |
| IDE integrado | VS Code + LLDB |
| Erros de memória | Valgrind (Linux) |

## Próximos Passos

Agora que você domina debugging em Zig:

1. 📊 [Testes em Zig: Guia Completo](/tutoriais/testes-zig/) — Escreva testes para prevenir bugs
2. 💾 [Gerenciamento de Memória em Zig](/tutoriais/gerenciamento-de-memoria-zig/) — Entenda allocators em profundidade
3. 🔧 [Zig Build System](/tutoriais/zig-build-system/) — Configure builds otimizados
4. 📚 [Documentação de Debugging do Zig](https://ziglang.org/documentation/master/#Debugging) — Referência oficial

---

*Tem dúvidas sobre debugging em Zig? Compartilhe com a comunidade!*
