C Mastery / Custom Allocators: Pools, Arenas, Slabs
Part 4 — Memory Management

Custom Allocators: Pools, Arenas, Slabs

This chapter covers the three most important custom allocation strategies: pools, arenas, and slab allocators. These replace general-purpose malloc when you need deterministic behavior, less fragmentation, or faster allocation.

Why This Matters

General-purpose allocators are general. Custom allocators exploit knowledge of your allocation patterns (fixed sizes, short lifetimes, bulk cleanup) to be faster, more predictable, and less fragmented — essential in embedded, games, and high-performance systems.

Prerequisites

Core Concept

Pools

A pool (or fixed-size pool) allocates objects of a single size from a preallocated block. Allocation is O(1) (pop from a free list), no fragmentation for that size, and no per-object metadata overhead beyond the free-list pointer.

Arenas

An arena (or bump/linear allocator) hands out memory by bumping a pointer forward. Individual objects are never freed; the entire arena is reset at once. Ideal for short-lived, group-lifetime data (a parser, a frame, a request).

Slabs

A slab allocator groups objects of the same size into contiguous slabs and manages them together. It reduces fragmentation and improves cache locality. It is the strategy behind many kernel allocators.

Examples

Bump arena

#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>

typedef struct {
    unsigned char *base;
    size_t size;
    size_t used;
} Arena;

static size_t align_up(size_t n, size_t a)
{
    return (n + a - 1) & ~(a - 1);
}

void *arena_alloc(Arena *a, size_t size, size_t align)
{
    size_t off = align_up(a->used, align);
    if (off + size > a->size)
        return NULL;
    void *p = a->base + off;
    a->used = off + size;
    return p;
}

void arena_reset(Arena *a)
{
    a->used = 0;
}

Fixed-size pool (free list)

typedef struct Block {
    struct Block *next;
} Block;

typedef struct {
    Block *free_list;
    size_t block_size;
} Pool;

void *pool_alloc(Pool *p)
{
    if (p->free_list == NULL)
        return NULL;
    Block *b = p->free_list;
    p->free_list = b->next;
    return b;
}

void pool_free(Pool *p, void *ptr)
{
    Block *b = ptr;
    b->next = p->free_list;
    p->free_list = b;
}

The free list stores the next pointer *inside* each free block, so no extra per-object allocation is needed.

How It Works

A bump arena advances a cursor and never reclaims individual objects; reset moves the cursor back to zero. A pool keeps a singly-linked list of free blocks, pushing and popping in O(1). A slab allocator partitions memory into same-size objects and tracks which are free, often with a bitmap.

Variations

Thread-local arenas

Give each thread its own arena to avoid lock contention; merge/reclaim at the end of a phase.

Stack-like arenas

Support arena_mark/arena_restore so you can roll back to a previous cursor, freeing a whole suffix of allocations at once.

Common Mistakes

not from malloc).

Undefined Behavior

Portability

source (e.g., mmap vs. a static buffer) may be platform-specific.

Under the Hood

A bump arena is a few pointer additions. A pool is a linked-list push/pop. A slab allocator is a bitmap plus arithmetic. All avoid the general allocator's search and coalescing costs, which is why they are faster and more predictable.

Practical Usage

objects (parsing, building an AST).

Exercises

1. Implement a bump arena with arena_alloc and arena_reset, and test it. 2. Implement a fixed-size pool with pool_alloc/pool_free. 3. Write a small test that allocates many objects from a pool and frees them; verify no leaks and O(1) behavior. 4. Explain why you must not call free on arena/pool pointers.

Deep Challenge

Implement a slab allocator that serves three size classes (e.g., 16, 64, 256 bytes) from a large block, using a free list per size class. Explain the trade-offs vs. a single-size pool and a bump arena.

References

(e.g., "slab allocator" in kernel design).

Verification

VERIFIED (as correct C code)

verified.`

Progress

Concept checkboxes

Mastery levels

ConceptCurrent level (0–8)Target level
c.mem.custom-alloc06
c.mem.pool06
c.mem.arena06
c.mem.slab05