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