What is the complete guide and common issues for dynamic memory management in C language?
Dynamic Memory Allocation Functions:
-
malloc - Allocate Memory
cvoid *malloc(size_t size); // Allocate specified number of bytes int *arr = (int*)malloc(10 * sizeof(int)); if (arr == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } // Use memory for (int i = 0; i < 10; i++) { arr[i] = i * i; } // Free memory free(arr); -
calloc - Allocate and Initialize
cvoid *calloc(size_t num, size_t size); // Allocate and initialize to zero int *arr = (int*)calloc(10, sizeof(int)); // All elements automatically initialized to 0 free(arr); -
realloc - Reallocate
cvoid *realloc(void *ptr, size_t size); int *arr = (int*)malloc(5 * sizeof(int)); // Expand memory int *new_arr = (int*)realloc(arr, 10 * sizeof(int)); if (new_arr == NULL) { free(arr); // Original memory still valid exit(1); } arr = new_arr; free(arr); -
free - Free Memory
cvoid free(void *ptr); int *ptr = (int*)malloc(sizeof(int)); free(ptr); ptr = NULL; // Avoid dangling pointers
Memory Management Best Practices:
-
Check Allocation Results
cvoid *ptr = malloc(size); if (ptr == NULL) { // Handle memory allocation failure return NULL; } -
Avoid Memory Leaks
cvoid function_with_leak() { int *ptr = malloc(sizeof(int)); // Forgot free(ptr) - memory leak } void correct_function() { int *ptr = malloc(sizeof(int)); if (ptr) { // Use memory free(ptr); } } -
Prevent Dangling Pointers
cint *ptr = malloc(sizeof(int)); free(ptr); ptr = NULL; // Avoid using freed memory // Wrong example *ptr = 10; // Undefined behavior -
Double Free Protection
cint *ptr = malloc(sizeof(int)); free(ptr); ptr = NULL; // Set to NULL free(ptr); // free(NULL) is safe
Common Issues and Solutions:
-
Memory Fragmentation
c// Problem: Frequent allocation and deallocation of different sizes for (int i = 0; i < 1000; i++) { void *ptr = malloc(rand() % 1000); free(ptr); } // Solution: Use memory pools or fixed-size allocation -
Buffer Overflow
c// Dangerous int *arr = malloc(10 * sizeof(int)); arr[10] = 100; // Out of bounds access // Safe int *arr = malloc(10 * sizeof(int)); if (index < 10) { arr[index] = value; } -
Wild Pointers
cint *ptr; // Uninitialized *ptr = 10; // Undefined behavior // Correct approach int *ptr = NULL; ptr = malloc(sizeof(int)); if (ptr) { *ptr = 10; free(ptr); ptr = NULL; }
Advanced Techniques:
-
Custom Memory Allocator
cvoid* my_malloc(size_t size) { void *ptr = malloc(size); if (ptr) { memset(ptr, 0, size); // Zero out } return ptr; } -
Memory Debugging
c#ifdef DEBUG void *debug_malloc(size_t size, const char *file, int line) { void *ptr = malloc(size); printf("Allocated %zu bytes at %p (%s:%d)\n", size, ptr, file, line); return ptr; } #define MALLOC(size) debug_malloc(size, __FILE__, __LINE__) #else #define MALLOC(size) malloc(size) #endif