---
title: "Como Usar GeneralPurposeAllocator em Zig"
url: "https://ziglang.com.br/receitas/como-usar-generalpurposeallocator-em-zig/"
markdown_url: "https://ziglang.com.br/receitas/como-usar-generalpurposeallocator-em-zig.MD"
description: "Aprenda a usar o GeneralPurposeAllocator (GPA) em Zig, o alocador versátil para uso geral com detecção de erros de memória e double-free."
date: "2026-02-21"
author: "Zig Brasil"
---

# Como Usar GeneralPurposeAllocator em Zig

Aprenda a usar o GeneralPurposeAllocator (GPA) em Zig, o alocador versátil para uso geral com detecção de erros de memória e double-free.


## Introdução

O `GeneralPurposeAllocator` (GPA) é o alocador de uso geral recomendado em Zig para desenvolvimento e depuração. Ele fornece detecção de erros como double-free, use-after-free e vazamentos de memória, além de stack traces para ajudar a encontrar bugs. Em produção, pode ser substituído por alocadores mais performáticos como `std.heap.c_allocator`.

Nesta receita, você aprenderá a usar o GPA e entenderá suas funcionalidades de debug.

## 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 GPA

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

pub fn main() !void {
    // Criar GPA com configuração padrão
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer {
        const status = gpa.deinit();
        if (status == .leak) {
            std.debug.print("AVISO: Vazamento de memória detectado!\n", .{});
        }
    }

    const allocator = gpa.allocator();

    // Alocar memória
    const dados = try allocator.alloc(u8, 100);
    defer allocator.free(dados);

    // Usar a memória
    @memset(dados, 0);
    @memcpy(dados[0..5], "Zig!\n");

    std.debug.print("{s}", .{dados[0..5]});
    std.debug.print("Alocados {d} bytes\n", .{dados.len});
}
```

## Alocar Tipos Específicos

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

const Ponto = struct {
    x: f64,
    y: f64,

    pub fn distancia(self: Ponto, outro: Ponto) f64 {
        const dx = self.x - outro.x;
        const dy = self.y - outro.y;
        return @sqrt(dx * dx + dy * dy);
    }
};

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

    // Alocar um único struct
    const p1 = try allocator.create(Ponto);
    defer allocator.destroy(p1);
    p1.* = .{ .x = 3.0, .y = 4.0 };

    const p2 = try allocator.create(Ponto);
    defer allocator.destroy(p2);
    p2.* = .{ .x = 0.0, .y = 0.0 };

    const dist = p1.distancia(p2.*);
    std.debug.print("Ponto 1: ({d:.1}, {d:.1})\n", .{ p1.x, p1.y });
    std.debug.print("Ponto 2: ({d:.1}, {d:.1})\n", .{ p2.x, p2.y });
    std.debug.print("Distância: {d:.2}\n", .{dist});

    // Alocar slice de structs
    const pontos = try allocator.alloc(Ponto, 5);
    defer allocator.free(pontos);

    for (pontos, 0..) |*p, i| {
        const fi: f64 = @floatFromInt(i);
        p.* = .{ .x = fi * 2.0, .y = fi * 3.0 };
    }

    std.debug.print("\nPontos alocados:\n", .{});
    for (pontos, 0..) |p, i| {
        std.debug.print("  [{d}] ({d:.1}, {d:.1})\n", .{ i, p.x, p.y });
    }
}
```

## Duplicar Dados

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

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

    // Duplicar string
    const original = "Aprendendo Zig em português";
    const copia = try allocator.dupe(u8, original);
    defer allocator.free(copia);

    std.debug.print("Original: {s}\n", .{original});
    std.debug.print("Cópia:    {s}\n", .{copia});
    std.debug.print("São o mesmo ponteiro? {}\n", .{original.ptr == copia.ptr});

    // Duplicar slice de inteiros
    const nums = [_]i32{ 10, 20, 30, 40, 50 };
    const nums_copia = try allocator.dupe(i32, &nums);
    defer allocator.free(nums_copia);

    std.debug.print("Cópia dos números: ", .{});
    for (nums_copia) |n| std.debug.print("{d} ", .{n});
    std.debug.print("\n", .{});
}
```

## Realocar Memória

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

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

    // Alocar inicialmente
    var buffer = try allocator.alloc(u8, 10);
    @memset(buffer, 'A');
    std.debug.print("Tamanho inicial: {d}\n", .{buffer.len});

    // Realocar para mais espaço
    buffer = try allocator.realloc(buffer, 20);
    @memset(buffer[10..], 'B');
    std.debug.print("Após realloc: {d}\n", .{buffer.len});
    std.debug.print("Conteúdo: {s}\n", .{buffer});

    // Liberar
    allocator.free(buffer);
}
```

## Detecção de Vazamentos

O GPA detecta memória não liberada:

```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("\n=== VAZAMENTO DE MEMÓRIA DETECTADO ===\n", .{});
        } else {
            std.debug.print("\n=== Sem vazamentos! ===\n", .{});
        }
    }
    const allocator = gpa.allocator();

    // Alocação 1: corretamente liberada
    const dados1 = try allocator.alloc(u8, 100);
    defer allocator.free(dados1);

    // Alocação 2: corretamente liberada
    const dados2 = try allocator.alloc(u32, 50);
    defer allocator.free(dados2);

    std.debug.print("Todas as alocações serão liberadas corretamente\n", .{});
}
```

## GPA com Configurações Customizadas

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

pub fn main() !void {
    // GPA com configurações avançadas
    var gpa = std.heap.GeneralPurposeAllocator(.{
        .stack_trace_frames = 8, // Frames de stack trace para debug
        .enable_memory_limit = true, // Habilitar limite de memória
    }){};
    defer _ = gpa.deinit();

    // Definir limite de memória (opcional)
    gpa.setRequestedMemoryLimit(1024 * 1024); // 1MB máximo

    const allocator = gpa.allocator();

    // Tentar alocar dentro do limite
    const dados = try allocator.alloc(u8, 1000);
    defer allocator.free(dados);
    std.debug.print("Alocados 1000 bytes com sucesso\n", .{});

    // Verificar uso de memória
    std.debug.print("Memória usada aproximadamente: 1000 bytes\n", .{});
}
```

## Padrão: Escolher Alocador em Tempo de Execução

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

fn fazerTrabalho(allocator: std.mem.Allocator) !void {
    const dados = try allocator.alloc(u8, 256);
    defer allocator.free(dados);

    @memset(dados, 0);
    std.debug.print("Trabalho feito com {d} bytes\n", .{dados.len});
}

pub fn main() !void {
    // Em debug: GPA para detectar erros
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    // A função aceita qualquer alocador via interface
    try fazerTrabalho(gpa.allocator());

    // Em produção, poderia usar:
    // try fazerTrabalho(std.heap.c_allocator);
    // ou
    // try fazerTrabalho(std.heap.page_allocator);
}
```

## Dicas e Boas Práticas

1. **Use GPA durante o desenvolvimento**: A detecção de erros economiza horas de depuração.

2. **Sempre verifique `deinit()`**: O retorno indica se houve vazamentos.

3. **`defer` imediato**: Coloque `defer allocator.free(x)` logo após cada alocação.

4. **Aceite `std.mem.Allocator` como parâmetro**: Funções que alocam devem receber o alocador, permitindo trocar em produção.

5. **`page_allocator` para produção**: É mais simples e rápido quando não precisa de debug.

## Receitas Relacionadas

- [Usando ArenaAllocator](/receitas/zig-arena-allocator/) - Alocação em lote
- [Usando FixedBufferAllocator](/receitas/zig-fixed-buffer-allocator/) - Sem heap
- [Detectar Vazamentos de Memória](/receitas/zig-detectar-memory-leak/) - Debug avançado
- [Usando Pool Allocators](/receitas/zig-pool-allocator/) - Objetos de tamanho fixo

## Tutoriais Relacionados

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