Introduction
Memory management in C remains one of the most critical challenges for experienced developers. Unlike modern languages with garbage collection, C requires complete mastery of allocations, deallocations, and leak detection. This tutorial guides you through advanced techniques used in production: memory pools, custom allocators, and debugging tools. These skills enable you to write high-performance, embedded, or mission-critical applications. You will learn how to avoid memory leaks and optimize resource usage.
Prerequisites
- Mastery of pointers and standard dynamic memory
- Solid knowledge of C99 or C11
- Recent GCC or Clang compiler
- Tools such as Valgrind and AddressSanitizer
Basic Custom Allocator
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void* custom_malloc(size_t size) {
void* ptr = malloc(size);
if (!ptr) {
fprintf(stderr, "Allocation échouée pour %zu octets\n", size);
exit(EXIT_FAILURE);
}
memset(ptr, 0, size);
return ptr;
}
int main() {
int* arr = (int*)custom_malloc(10 * sizeof(int));
arr[0] = 42;
printf("Valeur : %d\n", arr[0]);
free(arr);
return 0;
}This simple allocator adds error checking and zero-initialization. It prevents uninitialized pointers, a common source of bugs in advanced environments.
Memory Pool for Fast Allocations
#include <stdio.h>
#include <stdlib.h>
#define POOL_SIZE 1024
typedef struct {
char buffer[POOL_SIZE];
size_t offset;
} MemoryPool;
void* pool_alloc(MemoryPool* pool, size_t size) {
if (pool->offset + size > POOL_SIZE) return NULL;
void* ptr = pool->buffer + pool->offset;
pool->offset += size;
return ptr;
}
int main() {
MemoryPool pool = {0};
int* data = (int*)pool_alloc(&pool, 4 * sizeof(int));
data[0] = 100;
printf("Donnée pool : %d\n", data[0]);
return 0;
}The memory pool pre-allocates a fixed block and distributes segments without repeated system calls. Ideal for real-time or high-frequency allocation applications.
Safe Deallocation with Macros
#include <stdio.h>
#include <stdlib.h>
#define SAFE_FREE(ptr) do { \
if (ptr) { free(ptr); ptr = NULL; } \
} while(0)
int main() {
int* ptr = malloc(sizeof(int));
*ptr = 55;
printf("Avant free : %d\n", *ptr);
SAFE_FREE(ptr);
if (ptr == NULL) printf("Pointeur sécurisé\n");
return 0;
}This macro prevents double frees and dangling pointers. It is essential in complex codebases with multiple exit paths.
Leak Detection with Instrumentation
#include <stdio.h>
#include <stdlib.h>
static size_t allocated = 0;
void* tracked_malloc(size_t size) {
void* p = malloc(size);
if (p) allocated += size;
return p;
}
void tracked_free(void* p, size_t size) {
free(p);
allocated -= size;
}
int main() {
int* x = tracked_malloc(100);
printf("Alloué : %zu\n", allocated);
tracked_free(x, 100);
printf("Restant : %zu\n", allocated);
return 0;
}This simple tracking system monitors allocations in real time. It serves as a foundation for more advanced tools such as wrappers around malloc/free.
Complete Example with Dynamic Structure
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node* next;
} Node;
Node* create_node(int val) {
Node* n = (Node*)malloc(sizeof(Node));
if (!n) return NULL;
n->value = val;
n->next = NULL;
return n;
}
void free_list(Node* head) {
while (head) {
Node* tmp = head;
head = head->next;
free(tmp);
}
}
int main() {
Node* head = create_node(1);
head->next = create_node(2);
printf("Liste créée\n");
free_list(head);
return 0;
}Complete implementation of a linked list with safe allocation and deallocation. Demonstrates proper management of complex dynamic structures.
Best Practices
- Always initialize pointers to NULL after free
- Use memory pools for frequent allocations
- Instrument code to track leaks during development
- Prefer fixed sizes when possible
- Always validate malloc return values
Common Mistakes to Avoid
- Forgetting to free nested allocations
- Freeing the same pointer twice
- Using pointers after free without setting them to NULL
- Ignoring error returns from allocation functions
Going Further
Deepen these concepts with our expert training on embedded systems and low-level performance. Discover our trainings.