pointers-memory · advanced · ~40 min

Bump-pointer arena allocator

Bump-pointer allocation + alignment math.

Challenge

Implement a bump-pointer arena: one big block of memory that hands out aligned slices by advancing a single offset. There is no per-object free — you reset or destroy the whole arena at once.

The arena type and API:

typedef struct { char *base; size_t size, used; } arena_t;
arena_t *arena_create(size_t size);
void    *arena_alloc(arena_t *a, size_t n, size_t align);
void     arena_reset(arena_t *a);
void     arena_destroy(arena_t *a);

Task

Implement the four functions (no main — the grader calls them):

  • arena_create allocates a size-byte block, with used starting at 0.
  • arena_alloc rounds used up to a multiple of align, then carves off the next n bytes and returns a pointer to them.
  • arena_reset sets used back to 0 (reusing the block).
  • arena_destroy frees the block and the arena struct.

Input

size and n are byte counts. align is a power of two (1, 2, 4, 8, 16, ...).

Output

arena_alloc returns an align-aligned pointer into the block, or NULL if the request (after alignment) would exceed size or overflow. The other functions return nothing (arena_create returns the new arena).

Example

arena_t *a = arena_create(1024);
void *p1 = arena_alloc(a, 100, 8);    ->   p1 is 8-byte aligned
void *p2 = arena_alloc(a, 200, 16);   ->   p2 is 16-byte aligned, p2 > p1
arena_alloc(a, 10000, 8)              ->   NULL   (won't fit)
arena_reset(a);                       ->   a->used == 0

Edge cases

  • n == 0: returns the current (aligned) bump location, uses no bytes.
  • A request that would push past size, or that overflows during alignment: return NULL.

Rules

  • No per-allocation metadata; no way to free an individual allocation.

Why this matters

Arenas are the secret weapon of every fast C codebase — Chromium's Skia, Postgres's per-query allocator, Lua's parser. You allocate fast and free everything at once.

Input format

size/n are byte counts; align is a power of two.

Output format

arena_alloc returns an aligned pointer or NULL; arena_create returns the arena; reset/destroy return nothing.

Constraints

No per-allocation metadata; no individual free. Guard against overflow before comparing to size.

Starter code

#include <stddef.h>
#ifndef ARENA_T_DEFINED
#define ARENA_T_DEFINED
typedef struct { char *base; size_t size, used; } arena_t;
#endif
arena_t *arena_create(size_t size);
void    *arena_alloc(arena_t *a, size_t n, size_t align);
void     arena_reset(arena_t *a);
void     arena_destroy(arena_t *a);

Common mistakes

Aligning with (used + align - 1) & ~(align - 1) but forgetting that ~(align-1) has the wrong type if align is int; not checking for arithmetic overflow before comparing to size.

Edge cases to handle

n == 0 returns a pointer (current bump location) but uses no bytes. Allocation that would push past size returns NULL.

Complexity

O(1) per alloc. O(1) reset.

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.