---
title: "Cheatsheet: Arena Pattern em Zig"
url: "https://ziglang.com.br/padroes/cheatsheet-arena-pattern-em-zig/"
markdown_url: "https://ziglang.com.br/padroes/cheatsheet-arena-pattern-em-zig.MD"
description: "Design pattern Arena implementado em Zig: alocação em bloco com liberação coletiva, ArenaAllocator, padrões de uso e otimização de memória. Guia completo em português."
date: "2026-02-21"
author: "Zig Brasil"
---

# Cheatsheet: Arena Pattern em Zig

Design pattern Arena implementado em Zig: alocação em bloco com liberação coletiva, ArenaAllocator, padrões de uso e otimização de memória. Guia completo em português.


# Arena Pattern em Zig

O Arena Pattern agrupa múltiplas alocações em uma única região de memória que é liberada toda de uma vez. Em vez de rastrear e liberar cada alocação individualmente, você aloca livremente durante uma fase de trabalho e libera tudo no final. Em Zig, `std.heap.ArenaAllocator` implementa esse padrão nativamente.

## Quando Usar

- Processamento de requisições (alocar para processar, liberar ao finalizar)
- Parsing e compilação (alocar AST, liberar após gerar código)
- Operações batch com tempo de vida definido
- Game frames (alocar entidades temporárias por frame)
- Qualquer operação com fase de alocação seguida de liberação total

## Implementação com ArenaAllocator

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

pub fn main() !void {
    // Allocator pai (quem realmente gerencia a memória)
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    // Arena: aloca rápido, libera tudo junto
    var arena = std.heap.ArenaAllocator.init(gpa.allocator());
    defer arena.deinit(); // libera TUDO de uma vez

    const alloc = arena.allocator();

    // Alocar livremente — sem precisar de free individual!
    const nome = try alloc.dupe(u8, "Zig Brasil");
    const numeros = try alloc.alloc(i32, 100);
    const buffer = try alloc.alloc(u8, 4096);

    // Usar os dados...
    _ = nome;
    for (numeros, 0..) |*n, i| n.* = @intCast(i);
    @memset(buffer, 0);

    // Ao final: arena.deinit() libera TUDO
    // Não precisa de defer alloc.free() para cada alocação!
}
```

## Arena por Requisição

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

const Requisicao = struct {
    metodo: []const u8,
    path: []const u8,
    corpo: []const u8,
};

const Resposta = struct {
    status: u16,
    corpo: []const u8,
};

fn processarRequisicao(
    arena_alloc: std.mem.Allocator,
    req: Requisicao,
) !Resposta {
    // Todas alocações temporárias usam a arena
    const path_normalizado = try std.fmt.allocPrint(arena_alloc, "/{s}", .{
        std.mem.trimLeft(u8, req.path, "/"),
    });

    var partes = std.ArrayList([]const u8).init(arena_alloc);
    var iter = std.mem.splitSequence(u8, path_normalizado, "/");
    while (iter.next()) |parte| {
        try partes.append(parte);
    }

    const corpo_resposta = try std.fmt.allocPrint(arena_alloc, "OK: {s} {s}", .{
        req.metodo, path_normalizado,
    });

    return .{
        .status = 200,
        .corpo = corpo_resposta,
    };
    // Nenhum free necessário — arena cuida de tudo
}

fn servidorLoop(parent_alloc: std.mem.Allocator) !void {
    // Simular processamento de requisições
    for (0..1000) |_| {
        // Nova arena para cada requisição
        var arena = std.heap.ArenaAllocator.init(parent_alloc);
        defer arena.deinit(); // limpa tudo ao final da requisição

        const req = Requisicao{
            .metodo = "GET",
            .path = "/api/dados",
            .corpo = "",
        };

        const resp = try processarRequisicao(arena.allocator(), req);
        _ = resp;
        // arena.deinit() limpa tudo — zero leaks, zero fragmentação
    }
}
```

## Arena com Reset (Reutilização)

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    var arena = std.heap.ArenaAllocator.init(gpa.allocator());
    defer arena.deinit();

    // Processar múltiplos batches reutilizando memória
    for (0..100) |batch| {
        const alloc = arena.allocator();

        // Alocar para este batch
        const dados = try alloc.alloc(u8, 1024);
        _ = dados;

        const resultado = try std.fmt.allocPrint(alloc, "Batch {d} processado", .{batch});
        _ = resultado;

        // Resetar arena — libera tudo mas MANTÉM a memória alocada do SO
        _ = arena.reset(.retain_capacity);
        // Próximo batch reutiliza a mesma memória — sem novas syscalls
    }
}
```

## Arena sobre Buffer Estático

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

pub fn main() !void {
    // Arena sobre buffer da stack — zero heap allocations!
    var buffer: [64 * 1024]u8 = undefined; // 64KB na stack
    var fba = std.heap.FixedBufferAllocator.init(&buffer);

    var arena = std.heap.ArenaAllocator.init(fba.allocator());
    defer arena.deinit();

    const alloc = arena.allocator();

    // Alocações vêm do buffer na stack
    const dados = try alloc.alloc(u8, 1024);
    _ = dados;
}
```

## Comparação: Sem Arena vs Com Arena

```zig
// SEM arena — muitos defers, fácil esquecer um
fn semArena(allocator: std.mem.Allocator) !void {
    const a = try allocator.alloc(u8, 100);
    defer allocator.free(a);

    const b = try allocator.alloc(u8, 200);
    defer allocator.free(b);

    const c = try allocator.alloc(u8, 300);
    defer allocator.free(c);

    // Cada alocação precisa de seu próprio free
}

// COM arena — um único defer limpa tudo
fn comArena(parent: std.mem.Allocator) !void {
    var arena = std.heap.ArenaAllocator.init(parent);
    defer arena.deinit(); // UM defer para tudo

    const alloc = arena.allocator();
    const a = try alloc.alloc(u8, 100);
    const b = try alloc.alloc(u8, 200);
    const c = try alloc.alloc(u8, 300);
    _ = a; _ = b; _ = c;
    // Simples, limpo, sem risco de leak
}
```

## Quando Evitar

- Alocações que precisam sobreviver além do escopo da arena
- Quando objetos têm tempos de vida muito diferentes
- Quando é preciso liberar objetos individualmente (use GPA)
- Objetos enormes que desperdiçariam memória se mantidos até o final

## Veja Também

- [Allocators](/cheatsheets/allocators/) — Todos os tipos de alocadores
- [Pool de Objetos](/padroes/pool-objetos/) — Reutilização individual
- [Flyweight](/padroes/flyweight/) — Compartilhar estado para economizar memória
- [FAQ Memória](/faq/faq-memoria/) — Perguntas sobre gerenciamento de memória
- [Troubleshooting: Memory Leak](/troubleshooting/zig-memory-leak-encontrar/) — Encontrar vazamentos
