A lightweight heap allocator written in C and x86-64 NASM assembly. Manages a 1GB static heap using a linked list of block headers, supporting allocation, freeing, and heap inspection.
The heap is a flat 1GB region defined in assembly (heap.asm) and exposed to C via the memspace symbol. Each allocation is preceded by a 4-byte header struct:
┌─────────────────────────────────────┐
│ header (4 bytes) │
│ w : 30 bits — block size │
│ alloced : 1 bit — in use flag │
│ reserved : 1 bit — unused │
├─────────────────────────────────────┤
│ user data (w * 4 bytes) │
└─────────────────────────────────────┘
Block sizes are stored in words (1 word = 4 bytes). The special sentinel value ZeroWords (0x3FFFFFFF) represents a zero-size block, used to mark the end of the heap.
| File | Description |
|---|---|
alloc.c |
Allocator implementation |
alloc.h |
Types, macros, and function declarations |
heap.asm |
64-bit NASM assembly — defines the 1GB heap |
Makefile |
Build system |
Allocates at least bytes bytes from the heap. Rounds up to the nearest 4-byte word boundary. Returns a pointer to the usable memory, or NULL on failure with errno set.
int8 *p = alloc(64);Frees a previously allocated block. Zeroes the memory and marks the block as free. Returns true on success. Sets errno to Err2xFree and returns NULL if the block is already free or invalid.
destroy(p);Macro that prints a map of all blocks on the heap — address, index, size in words, and allocation status.
show();Example output:
0x00404034 Alloc 1 = 2 alloced words
0x00404040 Alloc 2 = 499 alloced words
Empty header at 0x0040480c, moving on
0x00404814 Alloc 4 = 3 alloced words
Set in errno on failure:
| Constant | Value | Meaning |
|---|---|---|
ErrNoErr |
0 | No error |
ErrNoMem |
1 | Heap exhausted |
ErrUnknown |
2 | Unknown error |
Err2xFree |
4 | Double-free attempted |
allock(n) // alloc(n * 1024) — allocate n kilobytes
allocm(n) // alloc(n * 1024 * 1024) — allocate n megabytes
allocg(n) // allocm(n * 1024) — allocate n gigabytesRequires GCC and NASM.
makeProduces the alloc binary. PIE is disabled (-no-pie) because the heap uses absolute 32-bit relocations in the ASM.
make clean # remove build artifacts- Block splitting — if a free block is larger than requested,
mkallocsplits it and writes a new header for the remainder. - First-fit —
findblock_walks the list recursively and returns the first free block large enough to satisfy the request. - No coalescing — adjacent free blocks are not merged. Repeated alloc/free cycles on varied sizes will fragment the heap over time.
- No thread safety — no locking; not safe for concurrent use.
- Max allocation —
Maxwordscaps a single allocation at(1GB/4) - 1words.