Memory Allocator
Feb to Jun 2026
A drop-in replacement for malloc, free, calloc and realloc.
The problem
I had been calling malloc for two years without knowing what it did with the 24 bytes I asked for, or why a program that frees everything can still keep growing.
What I did
- Version one was a single free list with first fit, growing the heap with
sbrk. Everyfreewalked the whole list, so it was slow. - I split free blocks into 12 size classes and added boundary tags, so a freed block merges with its neighbours in constant time.
- Anything over 128 KiB now goes straight to
mmap. - Each thread got its own arena and lock.
What went wrong
The threaded version deadlocked the first time a program called fork. The child inherited an arena locked by a thread that no longer existed. pthread_atfork handlers that take every arena lock before the fork, and release them after, fixed it.
heap
- header
- in use
- free
malloc splits a free block. free merges it back with its neighbours.
malloc(24) and a free. The 48-byte free block splits in two, then a freed block merges with the free one beside it.Results
- slower than glibc on a million random allocations
- 9%
- bigger peak heap than glibc
- 18%
- tests over about 1,400 lines of C
- 86