pointers-memory · advanced · ~45 min

Project: 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 supported by malloc alignment (up to _Alignof(max_align_t)).

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 or NULL for zero size or allocation failure).

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, _Alignof(max_align_t));   ->   p2 has the supported alignment, 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, may consume alignment padding but reserves no payload 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

Optional project: combine ownership, bounds, and failure handling across an API.

Input format

size and n are byte counts. align is a power of two supported by malloc alignment (up to _Alignof(max_align_t)).

Output format

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 or NULL for zero size or allocation failure).

Constraints

An arena owns one byte block. Alignment must be a nonzero power of two no greater than _Alignof(max_align_t). Creation returns NULL on failure. Allocation returns a borrowed aligned slice or NULL without changing used on failure. Reset invalidates all prior slices; do not free a slice individually. A zero-sized arena request returns NULL. Reset/destroy accept NULL as a no-op.

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

Confusing offset alignment with arbitrary address alignment or assuming zero-byte requests can never consume padding.

Edge cases to handle

Invalid/unsupported alignment; exhausted space; padding overflow; zero-byte request may consume alignment padding; reset then reuse.

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.