Many high-performance systems (e.g. graphics engines, financial trading servers, databases) suffer from memory fragmentation and the overhead generated by frequent malloc/free or new/delete calls.
This component aims to provide a custom memory allocator (Memory Pool) that pre-allocates a contiguous block of memory, handling the allocation and deallocation of fixed-size blocks in constant time
-
Initialization: The system must be able to pre-allocate a contiguous memory pool, specifying the block size (
block_size) and the maximum number of blocks (block_count). -
Allocation ($O(1)$): It must return a pointer to a free block of the pool in constant time. If the pool is exhausted, it must return
NULL(or throw an exception in C++), or request a new contiguous block if configured in dynamic mode. - Deallocation ($O(1)$): It must mark a previously allocated block as available again in constant time, without returning it to the operating system immediately.
- Thread Safety: The pool must support concurrent access by multiple threads without memory corruption (optional, or configurable via a compile-time macro to maximize single-thread performance).
- No Memory Leaks: When the pool is destroyed, all pre-allocated memory must be returned to the operating system.
- Minimal Memory Overhead: The use of internal metadata to track free blocks (e.g. via an internal linked list or a bitmask) must be minimal.
- Compatibility: Written in standard ANSI C (or C++17) with no external dependencies.
The pool manages free memory using a Free List implicit within the blocks themselves. When a block is free, its first bytes are used to store a pointer to the next free block. This zeroes the metadata overhead for unused blocks.
+-------------------------------------------------------------------+
| Memory Pool |
+-------------------------------------------------------------------+
| [Block 1 (Free)] -> Holds a pointer to Block 2 |
| [Block 2 (Allocated)] -> Holds user data |
| [Block 3 (Free)] -> Holds a pointer to Block 4 |
| [Block 4 (Free)] -> Holds NULL (end of list) |
+-------------------------------------------------------------------+
typedef struct memory_pool memory_pool_t;
// Initialize the memory pool
memory_pool_t* memory_pool_create(size_t block_size, size_t block_count);
// Allocate a block from the pool (O(1))
void* memory_pool_alloc(memory_pool_t* pool);
// Release a block back into the pool (O(1))
void memory_pool_free(memory_pool_t* pool, void* block);
// Destroy the pool, releasing all memory back to the operating system
void memory_pool_destroy(memory_pool_t* pool);- Correctness Tests: Allocate all blocks until exhaustion; verify the behaviour with null inputs or pointers foreign to the pool.
- Leak Verification (Valgrind):
-
Verification command:
gcc -g -O0 test_pool.c memory_pool.c -o test_pool valgrind --leak-check=full --show-leak-kinds=all ./test_pool
-
Success criterion:
ERROR SUMMARY: 0 errors from 0 contexts.
-
- Performance Benchmark: Compare the execution times of
memory_pool_alloc/freeagainst standardmalloc/freeover a loop of 1,000,000 iterations.