Custom Memory Allocators

an arena / region (bump) allocator

Imagine a long roll of receipt paper and a pen. Every time you need to write something down, you just write at the current position and slide the pen forward by however much you wrote. You never go back to erase a single entry — there is no eraser. When the whole job is done, you throw away the entire roll at once. That is an arena allocator: you allocate by simply moving a pointer forward (a bump), and you free everything together in one stroke. There is no per-object free.

Mechanically it is almost laughably simple. The arena holds one big buffer and a single pointer, often called the bump pointer, marking the boundary between used and free. To allocate n bytes you round n up for alignment, check that there is room, return the current pointer, and advance it by n. That is it — allocation is a handful of instructions with no searching, no free list, no headers. The catch is that there is no individual free: free(p) does nothing meaningful, because nothing tracks where p ended or whether anyone after it is still live. Reclamation happens only by resetting the whole arena: set the bump pointer back to the start (or release the buffer). At that instant every object in the arena is gone at once.

This is a perfect fit for phase-based work where many objects share one lifetime: parsing a file (allocate all the AST nodes, process them, free the arena), serving one web request (allocate everything for that request, drop it all when the response is sent), or one frame of a game. It is blazing fast and has essentially zero per-object bookkeeping overhead, and it sidesteps fragmentation and use-after-free of individual objects entirely. The honest limit: it is useless when objects have independent, interleaved lifetimes — if some objects in the arena must outlive others, you cannot reclaim memory until the very last one is done, so a long-lived object pins the whole region.

typedef struct { char *buf; size_t used, cap; } Arena; void *arena_alloc(Arena *a, size_t n) { n = (n + 15) & ~(size_t)15; /* round up to 16-byte alignment */ if (a->used + n > a->cap) return NULL; void *p = a->buf + a->used; /* hand out current position */ a->used += n; /* bump the pointer forward */ return p; } void arena_reset(Arena *a) { a->used = 0; } /* free EVERYTHING at once */

Allocation is just bump the pointer; there is no per-object free, only a whole-arena reset.

An arena gives speed by giving up individual reclamation: you cannot free one object early. It is ideal only when a batch of objects truly share one lifetime; mixing in long-lived objects defeats it.

Also called
region allocatorbump allocatorpointer-bump allocatorlinear allocatormonotonic allocator區域配置器線性配置器