Dynamic Memory Allocation
Prerequisites: Pointers deep dive
Arrays declared with a fixed size (int nums[5]) live on the
stack and must have a size known at compile time (or, in C99+,
at least at the point of declaration). malloc instead requests
memory from the heap at runtime, sized however the program
needs — and that memory must be explicitly released with free
when done.
Syntax
#include <stdlib.h>
int *nums = malloc(5 * sizeof(int));
if (nums == NULL) {
// allocation failed — handle it, don't just proceed
}
nums[0] = 10;
free(nums);
nums = NULL; // avoid an accidental later use
Example
int n = 5;
int *nums = malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
nums[i] = i * i;
}
for (int i = 0; i < n; i++) {
printf("%d\n", nums[i]);
}
free(nums);
Expected output
0
1
4
9
16
calloc(n, size) allocates and zero-initializes; realloc(ptr, newSize) resizes a previous allocation, possibly moving it (always
reassign its result — it may not equal the original pointer).
Common mistakes
- Forgetting to check
malloc's return value forNULLbefore using it — a failed allocation returnsNULL, and dereferencing that crashes. - Calling
freeon the same pointer twice ("double free") — this is undefined behavior, and often crashes later, unpredictably. - Using memory after
freeing it ("use-after-free") — a serious class of bug that even shows up as a real security vulnerability class in production software.
Practice
Allocate an array of 10 ints with malloc, fill it with the
squares of 0–9, print them, then free it.
Show solution
int *squares = malloc(10 * sizeof(int));
for (int i = 0; i < 10; i++) {
squares[i] = i * i;
printf("%d\n", squares[i]);
}
free(squares);