When we call malloc() or free(), the interface looks deceptively simple.
void *ptr = malloc(size);free(ptr);
But underneath those two calls, a memory allocator has to answer several non-trivial questions.
If free() only receives a pointer, how does it know the size of the block being released?
How are free blocks tracked?
What happens when the available block is larger than the requested allocation?
Which free block should be selected – first-fit, best-fit, or worst-fit?
And once memory is freed, how do we prevent the heap from slowly turning into many small unusable fragments?
These are not just implementation details. They determine allocation latency, fragmentation, memory utilization, and ultimately how predictable the system behaves.
A typical allocator may maintain metadata alongside allocated blocks, organize available memory using a free list or bitmap, split larger blocks during allocation, and later coalesce adjacent free blocks when memory is returned.
The allocation strategy itself also matters. First-fit favors speed, best-fit attempts to reduce immediate wasted space, while worst-fit takes a very different approach by allocating from the largest available region. None of them is universally “best” – the correct choice depends on the system constraints and allocation patterns.
This short write-up looks at some of the implementation problems that appear when designing a memory allocator:
- Tracking allocation metadata
- Maintaining free blocks
- Splitting memory blocks
- Selecting blocks for allocation
- Reusing and coalescing freed memory
- Understanding first-fit, best-fit, and worst-fit
Especially in resource-constrained systems, memory management is not simply about allocating bytes. The allocator itself becomes part of the system design.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An Article by: Yashwanth Naidu Tikkisetty
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
