Dynamic Memory Allocation in C
Dynamic memory allocation allows a program to request and release memory at runtime from the heap (unlike static variables which use stack or data segment).
Essential when:
- Size of array/structure is not known at compile time
- Need to create large data structures
- Want to resize memory during execution
- Managing memory efficiently in data structures (linked list, trees, graphs)
Four Main Functions for Dynamic Memory
| Function | Header | Purpose | Initializes memory? | Returns on failure |
|---|---|---|---|---|
| malloc() | Allocate block of memory | No (garbage values) | NULL | |
| calloc() | Allocate + initialize to zero | Yes (all bytes 0) | NULL | |
| realloc() | Resize previously allocated block | Preserves old data | NULL | |
| free() | Release allocated memory | — | — |
1. malloc() - Allocate Memory
C
Dynamic array using malloc
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
printf("Enter number of elements: ");
scanf("%d", &n);
int *arr = (int*)malloc(n * sizeof(int));
if(arr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
for(int i = 0; i < n; i++) {
arr[i] = i * 10;
}
printf("Array elements: ");
for(int i = 0; i < n; i++) printf("%d ", arr[i]);
free(arr); // Very important!
arr = NULL; // Good practice
return 0;
}
2. calloc() - Allocate & Zero-initialize
C
int *matrix = (int*)calloc(5 * 5, sizeof(int)); // 5×5 matrix, all zeros
// Safer than malloc + manual loop to set zeros
3. realloc() - Resize Memory
C
Dynamic growing array
int capacity = 5;
int *arr = (int*)malloc(capacity * sizeof(int));
int count = 0;
// Adding elements...
if(count == capacity) {
capacity *= 2;
int *temp = (int*)realloc(arr, capacity * sizeof(int));
if(temp == NULL) {
printf("Reallocation failed!\n");
free(arr);
return 1;
}
arr = temp;
}
// Later when done:
free(arr);
arr = NULL;
4. Common Problems & Dangers
| Problem | Description | How to Avoid |
|---|---|---|
| Memory Leak | Forget to call free() | Always pair malloc/calloc/realloc with free |
| Dangling Pointer | Use pointer after free() | Set pointer = NULL after free |
| Double Free | free() same memory twice | Set pointer = NULL after free |
| Use after realloc failure | Continue using old pointer | Check if realloc returned NULL |
| Access beyond allocated | Out of bounds | Keep track of size/capacity |
5. Best Practices (Modern C Style)
- Always check if allocation succeeded
- Use `sizeof(*ptr)` instead of type name
- Prefer `calloc` when you need zero-initialized memory
- Set pointer to NULL after free
- Don't cast malloc in C (optional but common)
- Use tools like Valgrind to detect leaks
- Modern style (C11+):
- ```c int *arr = malloc(n * sizeof(*arr)); ```
Codecrown