pointers-memory · advanced · ~15 min
Build an O(1) fixed-size block pool allocator using an embedded singly-linked freelist.
Fixed-size block pool allocators partition a contiguous memory buffer into identical chunks. Free chunks store a pointer to the next free chunk directly inside themselves, providing $O(1)$ allocation and deallocation without heap fragmentation.
Implement:
struct pool_block {
struct pool_block *next;
};
struct pool {
void *buffer;
size_t buf_size;
size_t block_size;
struct pool_block *free_head;
};
void pool_init(struct pool *p, void *buffer, size_t buf_size, size_t block_size);
void *pool_alloc(struct pool *p);
void pool_free(struct pool *p, void *ptr);
pool_init:p == NULL, buffer == NULL, or block_size < sizeof(struct pool_block), do nothing.buffer into buf_size / block_size consecutive blocks.next pointer to the subsequent block. The last block's next is NULL.p->free_head to point to the first block.pool_alloc:p == NULL or p->free_head == NULL (pool exhausted), return NULL.p->free_head, advancing free_head to free_head->next.pool_free:p == NULL or ptr == NULL, do nothing.ptr back onto the front of p->free_head as the new head.p: pool struct pointer; buffer: memory slab; buf_size: slab byte size; block_size: size per chunk.
pool_alloc returns allocated block pointer or NULL. pool_free returns void.
Freestanding C11. No malloc/free. Embed freelist inside chunks.
#include <stddef.h>
/* The harness provides:
struct pool_block {
struct pool_block *next;
};
struct pool {
void *buffer;
size_t buf_size;
size_t block_size;
struct pool_block *free_head;
};
*/
void pool_init(struct pool *p, void *buffer, size_t buf_size, size_t block_size) {
(void)p; (void)buffer; (void)buf_size; (void)block_size;
}
void *pool_alloc(struct pool *p) {
(void)p;
return NULL;
}
void pool_free(struct pool *p, void *ptr) {
(void)p; (void)ptr;
}
Calculating next block address without casting to char* or uint8_t*; forgetting that block_size must be >= sizeof(struct pool_block).
buf_size < block_size results in empty pool; pool exhaustion returns NULL; freeing and re-allocating reuses blocks.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.