Why “Implicit”?
We don’t store pointers to the next free block. The list is implied by the size in the header. To find a free block, we must visit every block (allocated or free) sequentially until we find one that fits.
The Architecture:
- Block Format: Header + Payload + Footer (Boundary Tags).
- Traversal: Linear Scan (O(N)).
- Freeing: Very fast (just flip a bit).
- Coalescing: We will implement immediate coalescing using boundary tags.
Key Characteristic: The search path includes allocated blocks. This makes malloc slow (O(N)) when the heap is full of allocated chunks.
HEAP START HEAP END
| |
v v
+------+ +----------------+ +------+ +----------------+ +------+
| PROL | -> | Allocated | -> | FREE | -> | Allocated | -> | EPIL |
+------+ | Size: 32 | | S:48 | | Size: 16 | +------+
+----------------+ +------+ +----------------+
| Header: 32/1 | | H:48/0| | Header: 16/1 |
| [ User Data ] | | [ ? ]| | [ User Data ] |
| [ User Data ] | | [ ? ]| | |
| Footer: 32/1 | | F:48/0| | Footer: 16/1 |
+----------------+ +------+ +----------------+
^ | ^
| | |
(Must Visit) (Is Free) (Must Visit)
Pros & Cons
Simple: Easy to implement and debug.
Low Overhead: Only 8 bytes overhead per block.
Slow Allocation: $O(N)$ where $N$ is total blocks. As heap fills, malloc becomes incredibly slow.
No Splitting (Naive): The naive implementation wastes memory by returning the entire free block even if the user asked for a tiny slice.
The changes I had to adopt
- I am not using normal variables (like struct Block) because we cannot afford the memory overhead.
- I could use inline functions in C and the compiler would optimise them and it would work well too but here are the more reasons for using macros.
- Polymorphism: I don’t need to worry about input and output types with macros. This would have been an annoying and repititive task with functions.
- these macros act as my custom assembly like commands.
Learnings
- I learned that we can’t just slice memory anywhere. You must align to 8 or 16 bytes to satisfy hardware requirements.
- Knuth’s Boundary Tags Trick: I learned how replicating the header at the end of the block (the Footer) allows for O(1) bidirectional traversal. This turned coalescing from a linear search problem into a constant-time operation.
- Now I know the problem is with traversing every block. free or not. So now I can work on that and that is exactly what the explicit freelist allocator is.