A memory pool helps manage memory efficiently by dividing a big chunk into small fixed-size blocks. It makes allocating and freeing memory faster and predictable.
Memory pool (fixed-size block allocator) in Embedded C
typedef struct MemoryPool {
void *pool_start;
size_t block_size;
size_t total_blocks;
void *free_list;
} MemoryPool;
void MemoryPool_init(MemoryPool *mp, void *buffer, size_t block_size, size_t total_blocks);
void *MemoryPool_alloc(MemoryPool *mp);
void MemoryPool_free(MemoryPool *mp, void *block);The pool is created from a buffer you provide.
Blocks are all the same size for simplicity and speed.
MemoryPool mp; char buffer[1024]; MemoryPool_init(&mp, buffer, 32, 32);
void *block = MemoryPool_alloc(&mp);
if (block != NULL) {
// use the block
}MemoryPool_free(&mp, block);
This program creates a memory pool with 8 blocks of 16 bytes each. It allocates all blocks, tries to allocate one more (which fails), frees one block, and then allocates again successfully.
#include <stdio.h> #include <stddef.h> typedef struct MemoryPool { void *pool_start; size_t block_size; size_t total_blocks; void *free_list; } MemoryPool; void MemoryPool_init(MemoryPool *mp, void *buffer, size_t block_size, size_t total_blocks) { mp->pool_start = buffer; mp->block_size = block_size; mp->total_blocks = total_blocks; mp->free_list = buffer; // Link all blocks in the free list char *p = (char *)buffer; for (size_t i = 0; i < total_blocks - 1; i++) { *(void **)p = p + block_size; // next pointer p += block_size; } *(void **)p = NULL; // last block points to NULL } void *MemoryPool_alloc(MemoryPool *mp) { if (mp->free_list == NULL) { return NULL; // no free blocks } void *block = mp->free_list; mp->free_list = *(void **)block; // move free_list to next return block; } void MemoryPool_free(MemoryPool *mp, void *block) { *(void **)block = mp->free_list; mp->free_list = block; } int main() { char buffer[128]; MemoryPool mp; MemoryPool_init(&mp, buffer, 16, 8); // 8 blocks of 16 bytes void *blocks[8]; // Allocate all blocks for (int i = 0; i < 8; i++) { blocks[i] = MemoryPool_alloc(&mp); if (blocks[i] != NULL) { printf("Allocated block %d at %p\n", i, blocks[i]); } else { printf("Failed to allocate block %d\n", i); } } // Try to allocate one more block (should fail) void *extra = MemoryPool_alloc(&mp); if (extra == NULL) { printf("No more blocks available\n"); } // Free one block MemoryPool_free(&mp, blocks[3]); printf("Freed block 3\n"); // Allocate again (should succeed) void *new_block = MemoryPool_alloc(&mp); if (new_block != NULL) { printf("Allocated new block at %p\n", new_block); } return 0; }
Memory pools avoid fragmentation by using fixed-size blocks.
Always free blocks back to the pool to reuse memory.
Do not free blocks not allocated from the pool or double free.
A memory pool divides memory into fixed-size blocks for fast allocation.
It is useful in embedded and real-time systems to manage memory predictably.
Initialize the pool, allocate blocks, and free them when done.
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
