---
title: "Como Usar ArenaAllocator em Zig"
url: "https://ziglang.com.br/receitas/como-usar-arenaallocator-em-zig/"
markdown_url: "https://ziglang.com.br/receitas/como-usar-arenaallocator-em-zig.MD"
description: "Aprenda a usar ArenaAllocator em Zig para alocação em lote com liberação única. Ideal para parsing, processamento em fases e simplificação de gerenciamento de memória."
date: "2026-02-21"
author: "Zig Brasil"
---

# Como Usar ArenaAllocator em Zig

Aprenda a usar ArenaAllocator em Zig para alocação em lote com liberação única. Ideal para parsing, processamento em fases e simplificação de gerenciamento de memória.


## Introdução

O `ArenaAllocator` é um dos alocadores mais úteis em Zig. Ele aloca memória de um alocador subjacente e libera tudo de uma vez quando o arena é destruído. Isso é perfeito para cenários onde várias alocações têm o mesmo tempo de vida -- como parsing de dados, processamento de requisições ou construção de estruturas temporárias.

Nesta receita, você aprenderá quando e como usar o ArenaAllocator na prática.

## Pré-requisitos

- Zig instalado (versão 0.13+). Veja o [guia de instalação](/tutoriais/como-instalar-zig/)
- Conhecimento básico de Zig. Consulte a [introdução ao Zig](/tutoriais/introducao-ao-zig/)

## Uso Básico do ArenaAllocator

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

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

    // Criar arena com GPA como alocador subjacente
    var arena = std.heap.ArenaAllocator.init(gpa.allocator());
    defer arena.deinit(); // Libera TUDO de uma vez

    const allocator = arena.allocator();

    // Alocar sem precisar de defer/free individual
    const nome = try allocator.dupe(u8, "Zig Brasil");
    const numeros = try allocator.alloc(u32, 100);
    const mensagem = try std.fmt.allocPrint(allocator, "Olá, {s}!", .{nome});

    // Usar normalmente
    for (numeros, 0..) |*n, i| {
        n.* = @intCast(i * 2);
    }

    std.debug.print("Nome: {s}\n", .{nome});
    std.debug.print("Mensagem: {s}\n", .{mensagem});
    std.debug.print("Primeiro número: {d}\n", .{numeros[0]});
    std.debug.print("Último número: {d}\n", .{numeros[99]});

    // Não precisa de free individual -- arena.deinit() cuida de tudo
}
```

## Arena para Processamento de Dados

Ideal quando você processa dados em fases:

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

const Registro = struct {
    nome: []const u8,
    valor: f64,
};

fn processarCSV(allocator: std.mem.Allocator, csv: []const u8) ![]Registro {
    var registros = std.ArrayList(Registro).init(allocator);

    var linhas = std.mem.splitScalar(u8, csv, '\n');
    while (linhas.next()) |linha| {
        if (linha.len == 0) continue;

        var campos = std.mem.splitScalar(u8, linha, ',');
        const nome_raw = campos.next() orelse continue;
        const valor_raw = campos.next() orelse continue;

        const nome = try allocator.dupe(u8, std.mem.trim(u8, nome_raw, " "));
        const valor = std.fmt.parseFloat(f64, std.mem.trim(u8, valor_raw, " ")) catch continue;

        try registros.append(.{ .nome = nome, .valor = valor });
    }

    return registros.toOwnedSlice();
}

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

    // Arena para todo o processamento
    var arena = std.heap.ArenaAllocator.init(gpa.allocator());
    defer arena.deinit();

    const csv_data =
        \\Produto A, 29.90
        \\Produto B, 49.50
        \\Produto C, 15.00
        \\Produto D, 89.99
    ;

    const registros = try processarCSV(arena.allocator(), csv_data);

    std.debug.print("Registros processados:\n", .{});
    var total: f64 = 0;
    for (registros) |reg| {
        std.debug.print("  {s}: R$ {d:.2}\n", .{ reg.nome, reg.valor });
        total += reg.valor;
    }
    std.debug.print("Total: R$ {d:.2}\n", .{total});
    // arena.deinit() libera tudo automaticamente
}
```

## Reset para Reutilização

Use `reset` para liberar toda a memória e reusar o arena:

```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();

    const allocator = arena.allocator();

    // Fase 1: Processar dados
    const dados1 = try allocator.alloc(u8, 1000);
    @memset(dados1, 'A');
    std.debug.print("Fase 1: Alocados {d} bytes\n", .{dados1.len});

    // Liberar tudo da fase 1 e começar de novo
    _ = arena.reset(.retain_capacity);

    // Fase 2: Novos dados (reutiliza a memória)
    const dados2 = try allocator.alloc(u8, 500);
    @memset(dados2, 'B');
    std.debug.print("Fase 2: Alocados {d} bytes\n", .{dados2.len});

    // Fase 3
    _ = arena.reset(.retain_capacity);
    const dados3 = try allocator.alloc(u8, 200);
    @memset(dados3, 'C');
    std.debug.print("Fase 3: Alocados {d} bytes\n", .{dados3.len});
}
```

## Arena para Construir Strings

Construir strings sem se preocupar em liberar cada pedaço:

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

fn construirRelatorio(allocator: std.mem.Allocator, itens: []const []const u8) ![]const u8 {
    var partes = std.ArrayList(u8).init(allocator);
    const writer = partes.writer();

    try writer.writeAll("=== RELATÓRIO ===\n\n");

    for (itens, 1..) |item, i| {
        try writer.print("{d}. {s}\n", .{ i, item });
    }

    try writer.print("\nTotal: {d} itens\n", .{itens.len});
    try writer.writeAll("=================\n");

    return partes.toOwnedSlice();
}

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

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

    const itens = [_][]const u8{
        "Estudar Zig",
        "Implementar servidor",
        "Escrever testes",
        "Revisar código",
    };

    const relatorio = try construirRelatorio(arena.allocator(), &itens);
    std.debug.print("{s}", .{relatorio});
}
```

## Quando Usar ArenaAllocator

| Cenário | Recomendado? |
|---|---|
| Parsing de dados | Sim |
| Processamento de requisição HTTP | Sim |
| Construção de strings temporárias | Sim |
| Objetos com tempos de vida diferentes | Não |
| Alocações de longa duração | Não |
| Cache em memória | Não |

## Dicas e Boas Práticas

1. **Um `defer arena.deinit()` substitui muitos `defer free()`**: Essa é a grande vantagem -- simplificação do gerenciamento de memória.

2. **Use com GPA em desenvolvimento**: `ArenaAllocator.init(gpa.allocator())` permite detectar bugs durante o desenvolvimento.

3. **`reset(.retain_capacity)` reutiliza memória**: Não libera para o OS, mas permite reutilizar os blocos alocados.

4. **Não misture tempos de vida**: Se alguns dados precisam sobreviver mais que outros, use alocadores separados.

5. **Arena dentro de arena**: Você pode criar sub-arenas para escopos mais curtos dentro de um processamento maior.

## Receitas Relacionadas

- [Usando GeneralPurposeAllocator](/receitas/zig-general-purpose-allocator/) - Alocador de uso geral
- [Usando FixedBufferAllocator](/receitas/zig-fixed-buffer-allocator/) - Alocação sem heap
- [Detectar Vazamentos de Memória](/receitas/zig-detectar-memory-leak/) - Debug de memória
- [Como parsear JSON em Zig](/receitas/zig-parse-json/) - Parsing com arena

## Tutoriais Relacionados

- [Gerenciamento de Memória em Zig](/tutoriais/gerenciamento-de-memoria-zig/)
- [Introdução ao Zig](/tutoriais/introducao-ao-zig/)
