Memory pool (fixed-size block allocator) in Embedded C - Step-by-Step Execution
typedef struct Block {
struct Block* next;
} Block;
Block* pool = NULL;
void init_pool(Block* blocks, int count) {
for (int i = 0; i < count - 1; i++) {
blocks[i].next = &blocks[i+1];
}
blocks[count-1].next = NULL;
pool = &blocks[0];
}
Block* allocate() {
if (!pool) return NULL;
Block* block = pool;
pool = pool->next;
return block;
}
void free_block(Block* block) {
block->next = pool;
pool = block;
}| Step | Action | Pool State (addresses) | Allocated Block | Output |
|---|---|---|---|---|
| 1 | Initialize pool with 3 blocks | &blocks[0] -> &blocks[1] -> &blocks[2] -> NULL | NULL | Pool ready |
| 2 | allocate() called | &blocks[1] -> &blocks[2] -> NULL | &blocks[0] | Block allocated: &blocks[0] |
| 3 | allocate() called | &blocks[2] -> NULL | &blocks[1] | Block allocated: &blocks[1] |
| 4 | allocate() called | NULL | &blocks[2] | Block allocated: &blocks[2] |
| 5 | allocate() called | NULL | NULL | No blocks left, return NULL |
| 6 | free_block(&blocks[1]) called | &blocks[1] -> NULL | NULL | Block &blocks[1] returned to pool |
| 7 | allocate() called | NULL | &blocks[1] | Block allocated: &blocks[1] |
| 8 | free_block(&blocks[0]) called | &blocks[0] -> NULL | NULL | Block &blocks[0] returned to pool |
| 9 | free_block(&blocks[2]) called | &blocks[2] -> &blocks[0] -> NULL | NULL | Block &blocks[2] returned to pool |
| 10 | allocate() called | &blocks[0] -> NULL | &blocks[2] | Block allocated: &blocks[2] |
| 11 | allocate() called | NULL | &blocks[0] | Block allocated: &blocks[0] |
| 12 | allocate() called | NULL | NULL | No blocks left, return NULL |
| Variable | Start | After Step 1 | After Step 2 | After Step 3 | After Step 4 | After Step 5 | After Step 6 | After Step 7 | After Step 8 | After Step 9 | After Step 10 | After Step 11 | After Step 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| pool | NULL | &blocks[0] | &blocks[1] | &blocks[2] | NULL | NULL | &blocks[1] | NULL | &blocks[0] | &blocks[2] | &blocks[0] | NULL | NULL |
| allocated_block | NULL | NULL | &blocks[0] | &blocks[1] | &blocks[2] | NULL | NULL | &blocks[1] | NULL | NULL | &blocks[2] | &blocks[0] | NULL |
Memory pool manages fixed-size blocks. Initialize pool as linked list of free blocks. allocate() removes and returns first free block. free_block() adds block back to front of pool. Returns NULL if no blocks free. Simple, fast fixed-size memory management.
Practice
What is the main advantage of using a memory pool with fixed-size blocks in embedded systems?
Solution
Step 1: Understand memory pool purpose
A memory pool divides memory into fixed-size blocks to allocate memory quickly without fragmentation.Step 2: Identify advantage in embedded systems
Embedded systems need fast and predictable memory allocation, which memory pools provide.Final Answer:
Faster and predictable memory allocation -> Option CQuick Check:
Memory pool advantage = Faster and predictable memory allocation [OK]
- Confusing memory pools with dynamic resizing
- Thinking memory pools provide garbage collection
- Assuming memory pools allow unlimited memory
Which of the following is the correct way to declare a fixed-size memory pool array for 10 blocks of 32 bytes each in C?
?Solution
Step 1: Understand array dimensions
We want 10 blocks, each block is 32 bytes, so array should be 10 rows and 32 columns.Step 2: Match declaration syntax
char pool[10][32]; declares 10 blocks of 32 bytes each correctly.Final Answer:
char pool[10][32]; -> Option AQuick Check:
Array size = 10 blocks x 32 bytes [OK]
- Swapping dimensions (32 and 10)
- Using pointer array instead of fixed blocks
- Declaring a single large array without blocks
Given this simplified memory pool allocator code snippet, what will be the output?
char pool[3][16];
int free_blocks = 3;
char* allocate() {
if (free_blocks > 0) {
return pool[--free_blocks];
}
return NULL;
}
int main() {
char* p1 = allocate();
char* p2 = allocate();
char* p3 = allocate();
char* p4 = allocate();
printf("%p %p %p %p\n", p1, p2, p3, p4);
return 0;
}Solution
Step 1: Trace allocation calls
Initially free_blocks=3. Each allocate() call decrements free_blocks and returns pool[free_blocks]. So p1=pool[2], p2=pool[1], p3=pool[0], p4=NULL because free_blocks=0.Step 2: Understand output
First three pointers are valid addresses, last pointer is NULL.Final Answer:
Three valid pointers and one NULL pointer -> Option AQuick Check:
3 blocks allocated, 4th returns NULL [OK]
- Assuming pointers are all NULL
- Thinking pointers point to same block
- Forgetting to decrement free_blocks
Identify the bug in this memory pool free function and select the correct fix.
void free_block(char* block) {
if (free_blocks < MAX_BLOCKS) {
pool[free_blocks++] = block;
}
}Solution
Step 1: Analyze free_block logic
The pool array holds actual memory blocks, not pointers. Storing a pointer in pool overwrites data.Step 2: Correct way to free block
Freeing should mark the block as available in a separate structure or use a free list, not overwrite pool data.Final Answer:
Store pointer in pool array is wrong; should mark block as free differently -> Option DQuick Check:
Freeing must not overwrite pool memory [OK]
- Overwriting pool memory with pointers
- Not checking block validity
- Assuming pool holds pointers, not blocks
You want to implement a memory pool that supports 5 blocks of 64 bytes each. You also want to track which blocks are free using a bitmap (an integer where each bit represents a block's status: 0 = free, 1 = used). Which of the following code snippets correctly initializes the bitmap and allocates a block?
?Solution
Step 1: Understand bitmap meaning
Bitmap bit 0 means free, 1 means used. So initializing bitmap=0 means all blocks free.Step 2: Check allocation logic
Allocation finds first free bit (0), sets it to 1 (used), and returns that block.Final Answer:
Bitmap initialized to 0; allocate sets bit to 1 on allocation -> Option BQuick Check:
0 = free, set bit to 1 when used [OK]
- Initializing bitmap with all bits set (all used)
- Checking wrong bit condition for free blocks
- Setting bits incorrectly on allocation
Ready to prove it?
Pass the test and this pattern moves unknown
