---
title: "Encontrar Memory Leaks em Zig — Detectar Vazamentos de Memória"
url: "https://ziglang.com.br/troubleshooting/encontrar-memory-leaks-em-zig-detectar-vazamentos-de-mem%C3%B3ria/"
markdown_url: "https://ziglang.com.br/troubleshooting/encontrar-memory-leaks-em-zig-detectar-vazamentos-de-mem%C3%B3ria.MD"
description: "Guia para encontrar e corrigir memory leaks em Zig. Usar GeneralPurposeAllocator, testing.allocator, Valgrind, padrões comuns de vazamento e prevenção."
date: "2026-02-21"
author: "Zig Brasil"
---

# Encontrar Memory Leaks em Zig — Detectar Vazamentos de Memória

Guia para encontrar e corrigir memory leaks em Zig. Usar GeneralPurposeAllocator, testing.allocator, Valgrind, padrões comuns de vazamento e prevenção.


# Encontrar Memory Leaks em Zig — Detectar Vazamentos de Memória

Memory leaks ocorrem quando memória é alocada mas nunca liberada. Em Zig, o sistema de allocators facilita a detecção e correção de vazamentos. Este guia mostra como encontrar e resolver memory leaks no seu código.

## Usando GeneralPurposeAllocator para Detectar Leaks

O `GeneralPurposeAllocator` (GPA) é sua principal ferramenta. Em modo debug, ele rastreia todas as alocações e reporta leaks quando `deinit()` é chamado:

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer {
        const status = gpa.deinit();
        if (status == .leak) {
            std.debug.print("ALERTA: Memory leak detectado!\n", .{});
        }
    }
    const allocator = gpa.allocator();

    // Este código tem leak — alocou mas não liberou
    const dados = try allocator.alloc(u8, 1024);
    _ = dados;
    // Faltou: allocator.free(dados);
}
```

A saída do GPA inclui o **stack trace** da alocação que vazou, mostrando exatamente onde a memória foi alocada.

## Usando testing.allocator em Testes

Nos testes, `std.testing.allocator` falha automaticamente se detectar leaks:

```zig
test "sem memory leak" {
    const allocator = std.testing.allocator;

    const dados = try allocator.alloc(u8, 100);
    defer allocator.free(dados); // Sem isso, o teste FALHA

    // ...usar dados...
}
```

Se esquecer o `defer allocator.free(dados)`, o teste reportará o leak com stack trace.

## Padrões Comuns de Memory Leak

### 1. Esqueceu o `defer free`

```zig
// LEAK: alocou mas não liberou
fn processar(allocator: std.mem.Allocator) !void {
    const buffer = try allocator.alloc(u8, 4096);
    // ...usar buffer...
    // FALTOU: defer allocator.free(buffer);
}

// CORRETO:
fn processar(allocator: std.mem.Allocator) !void {
    const buffer = try allocator.alloc(u8, 4096);
    defer allocator.free(buffer);
    // ...usar buffer...
}
```

### 2. Return antes do defer

```zig
// LEAK: defer nunca é registrado se o early return acontecer antes
fn perigoso(allocator: std.mem.Allocator, cond: bool) ![]u8 {
    const a = try allocator.alloc(u8, 100);
    if (cond) return a; // OK — chamador libera
    const b = try allocator.alloc(u8, 200);
    defer allocator.free(a); // Se chegou aqui, 'a' é liberado
    return b; // Chamador libera 'b'
}
```

### 3. Leak em ArrayList ou HashMap

```zig
// LEAK: deinit libera a estrutura, mas não os itens alocados internamente
var lista = std.ArrayList([]u8).init(allocator);
defer lista.deinit();

// Se cada item foi alocado separadamente, precisa liberar cada um:
defer {
    for (lista.items) |item| allocator.free(item);
    lista.deinit();
}
```

### 4. Leak ao substituir valor em HashMap

```zig
var map = std.StringHashMap([]u8).init(allocator);
defer map.deinit();

// Ao fazer put, o valor ANTERIOR é perdido se já existia
// Precisa verificar e liberar o anterior
const result = try map.fetchPut("chave", novo_valor);
if (result) |kv| {
    allocator.free(kv.value); // Liberar o valor antigo
}
```

## Usando Valgrind

Para análise mais profunda, use Valgrind com binários Zig compilados em Debug:

```bash
# Compilar em modo Debug
zig build

# Rodar com Valgrind
valgrind --leak-check=full ./zig-out/bin/meu-app

# Saída mostra:
# ==12345== LEAK SUMMARY:
# ==12345==    definitely lost: 1,024 bytes in 1 blocks
# ==12345==    ...com stack trace da alocação
```

## Usando AddressSanitizer

Zig suporta compilação com sanitizers:

```bash
# Compilar com AddressSanitizer (detecta leaks, use-after-free, etc.)
zig build-exe src/main.zig -fsanitize=address

# Rodar normalmente — erros são reportados automaticamente
./main
```

## Estratégias de Prevenção

1. **Regra do defer imediato** — Sempre coloque `defer free` na linha seguinte à alocação
2. **Use ArenaAllocator** para alocações temporárias — libera tudo de uma vez
3. **Testes com testing.allocator** — Detectam leaks automaticamente
4. **GPA em desenvolvimento** — Sempre use GPA durante desenvolvimento
5. **Ownership claro** — Documente quem é responsável por liberar cada alocação

```zig
// ArenaAllocator para operações batch — sem leak possível
var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit(); // Libera TUDO de uma vez

const temp = arena.allocator();
// Muitas alocações temporárias sem precisar de free individual
```

## Checklist de Debugging

Quando encontrar um memory leak:

1. Ative o GPA e rode o programa
2. Leia o stack trace da alocação vazada
3. Encontre a linha que aloca a memória
4. Verifique se há `defer free` correspondente
5. Verifique todos os caminhos de retorno (incluindo erros)
6. Verifique se containers (ArrayList, HashMap) liberam seus itens

## Veja Também

- [FAQ Memória](/faq/faq-memoria/) — Conceitos de gerenciamento de memória
- [Crash em Runtime](/troubleshooting/zig-crash-runtime/) — Crashes relacionados a memória
- [Debugar Segfaults](/troubleshooting/zig-segfault-debugar/) — Use-after-free e acessos inválidos
- [Ler Stack Traces](/troubleshooting/zig-stack-trace-ler/) — Interpretar stack traces
- [Erros do Compilador](/erros/) — Erros de compilação relacionados a memória
