Dynamic Memory Allocation (Heap)
Dynamic memory allocation gives control over:
- when to allocate
- how much to allocate
- when to free
Used when:
- size unknown at compile time
- need resizable data structures
malloc()
void *malloc(size_t size);
- allocates bytes
- uninitialized memory
- returns NULL if fail
Example:
int *p = malloc(sizeof(int));
if(!p) return;
*p = 10;
free(p);
p = NULL;
calloc()
void *calloc(size_t n, size_t size);
- allocates n blocks
- initializes all to 0
realloc()
void *realloc(void *ptr, size_t newSize);
May move block. Use safe pattern:
int *tmp = realloc(p, newSize);
if(tmp) p = tmp; // else old p valid
Allocating arrays safely
int n = 10;
int *arr = malloc(n * sizeof(*arr));
free()
free(p);
p = NULL;
Dynamic Memory Allocation (malloc/free lifecycle) Diagram
Shows the lifecycle of dynamic allocation on heap using malloc/calloc, safe usage, and cleanup using free() and setting pointer to NULL.
Dynamic 2D array (important)
Method 1: row pointers
int r=3,c=4;
int **a = malloc(r*sizeof(*a));
for(int i=0;i<r;i++)
a[i] = malloc(c*sizeof(**a));
Free:
for(int i=0;i<r;i++) free(a[i]);
free(a);
Method 2: contiguous block (faster)
int *data = malloc(r*c*sizeof(int));
int (*a)[c] = (int (*)[c])data;
Common DMA bugs
1) memory leak
2) double free
3) use-after-free
4) forgetting NULL check
5) overflow write