Skip to main content

Overview

The Allocator interface is Zig’s standard abstraction for memory allocation. All allocators in Zig implement this common interface, providing a uniform API for memory management across different allocation strategies.

Structure

const Allocator = struct {
    ptr: *anyopaque,
    vtable: *const VTable,
};
ptr
*anyopaque
Type-erased pointer to the allocator implementation. May be set to undefined when the allocator has no associated state.
vtable
*const VTable
Pointer to the virtual function table containing the allocator’s implementation methods.

VTable Methods

The VTable struct defines the core allocation operations:

alloc

alloc: *const fn (*anyopaque, len: usize, alignment: Alignment, ret_addr: usize) ?[*]u8
Allocates memory with specified length and alignment.
len
usize
required
Number of bytes to allocate. Must be greater than zero.
alignment
Alignment
required
Required memory alignment.
ret_addr
usize
Return address for debugging. 0 means no return address provided.
return
?[*]u8
Pointer to allocated memory, or null if allocation failed.

resize

resize: *const fn (*anyopaque, memory: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) bool
Attempts to expand or shrink memory in place without moving it.
memory
[]u8
required
Existing allocation slice. Length must equal the most recent allocation size.
alignment
Alignment
required
Must match the alignment from the original allocation.
new_len
usize
required
Desired new size. Must be greater than zero.
return
bool
true if resize succeeded in place, false if relocation would be required.

remap

remap: *const fn (*anyopaque, memory: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) ?[*]u8
Attempts to expand or shrink memory, allowing relocation if necessary.
return
?[*]u8
Pointer to the resized memory (may be same address or relocated), or null if the allocator cannot perform the operation efficiently.

free

free: *const fn (*anyopaque, memory: []u8, alignment: Alignment, ret_addr: usize) void
Frees and invalidates a region of memory.
memory
[]u8
required
Memory to free. Length must match the most recent allocation size.
alignment
Alignment
required
Must match the alignment from the original allocation.

High-Level API

create

pub fn create(allocator: Allocator, comptime T: type) Error!*T
Allocates memory for a single object of type T.
T
type
required
The type to allocate.
return
*T
Pointer to uninitialized memory for the object.
Example:
const point = try allocator.create(Point);
point.* = Point{ .x = 10, .y = 20 };
defer allocator.destroy(point);

destroy

pub fn destroy(allocator: Allocator, ptr: anytype) void
Frees memory allocated by create.

alloc

pub fn alloc(allocator: Allocator, comptime T: type, n: usize) Error![]T
Allocates an array of n items of type T.
n
usize
required
Number of elements to allocate.
return
[]T
Slice of uninitialized memory.
Example:
const buffer = try allocator.alloc(u8, 1024);
defer allocator.free(buffer);

allocSentinel

pub fn allocSentinel(allocator: Allocator, comptime Elem: type, n: usize, comptime sentinel: Elem) Error![:sentinel]Elem
Allocates n + 1 items with a sentinel value at the end. Example:
const str = try allocator.allocSentinel(u8, 5, 0);
defer allocator.free(str);
// str is [:0]u8 (null-terminated)

alignedAlloc

pub fn alignedAlloc(allocator: Allocator, comptime T: type, comptime alignment: ?Alignment, n: usize) Error![]align(...) T
Allocates memory with custom alignment.
alignment
?Alignment
Desired alignment, or null for natural alignment.

realloc

pub fn realloc(allocator: Allocator, old_mem: anytype, new_n: usize) Error![]T
Resizes an existing allocation, relocating if necessary.
old_mem
slice
Existing allocation. May be empty (length 0).
new_n
usize
New element count. May be zero to free the allocation.
Example:
var buffer = try allocator.alloc(u8, 10);
// Need more space
buffer = try allocator.realloc(buffer, 100);
defer allocator.free(buffer);

free

pub fn free(allocator: Allocator, memory: anytype) void
Frees memory allocated by alloc, alignedAlloc, or realloc.
Freeing zero-length slices is a no-op.

dupe

pub fn dupe(allocator: Allocator, comptime T: type, m: []const T) Error![]T
Creates a copy of a slice. Example:
const original = "Hello";
const copy = try allocator.dupe(u8, original);
defer allocator.free(copy);

dupeZ

pub fn dupeZ(allocator: Allocator, comptime T: type, m: []const T) Error![:0]T
Creates a copy with a null terminator.

Error Type

pub const Error = error{OutOfMemory};
All allocator functions that can fail return Error!T, where the only possible error is OutOfMemory.

Alignment

pub const Alignment = enum(Log2Int(usize)) {
    @"1" = 0,
    @"2" = 1,
    @"4" = 2,
    @"8" = 3,
    @"16" = 4,
    @"32" = 5,
    @"64" = 6,
    _,
};
Alignments are stored as log2 values to save space.

Alignment Methods

toByteUnits() - Converts to byte alignment
const alignment: Alignment = .@"16";
const bytes = alignment.toByteUnits(); // 16
fromByteUnits(n: usize) - Creates from byte alignment
const alignment = Alignment.fromByteUnits(32);
of(comptime T: type) - Gets natural alignment of type
const alignment = Alignment.of(i64); // .@"8"
check(address: usize) - Verifies address alignment
if (alignment.check(@intFromPtr(ptr))) {
    // ptr is properly aligned
}

Common Allocators

page_allocator

Direct syscall-based allocator. Thread-safe but slow.
const std = @import("std");
const allocator = std.heap.page_allocator;

c_allocator

Wraps C’s malloc/free. Only available when linking libc.
const allocator = std.heap.c_allocator;

FixedBufferAllocator

Allocates from a fixed buffer. Fast but limited.
var buffer: [1024]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buffer);
const allocator = fba.allocator();

Best Practices

Use defer to ensure memory is freed:
const data = try allocator.alloc(u8, 100);
defer allocator.free(data);
  • Use destroy() for create()
  • Use free() for alloc(), realloc(), dupe()
  • Pass the same length and alignment used during allocation
Zero-length allocations are valid and return empty slices.
When making many allocations that have the same lifetime, use ArenaAllocator to free them all at once.

See Also

Build docs developers (and LLMs) love