Memory Architecture: Stack vs Heap (malloc, calloc, realloc, free)
1Concept
C memory is divided into Stack (fast, automatic, fixed size) and Heap (dynamic, manual lifetime). Dynamic memory is allocated via malloc(size) (uninitialized) or calloc(num, size) (zero-initialized), resized with realloc(), and MUST be freed with free(). Failing to call free() causes memory leaks; using memory after free() causes undefined behavior (use-after-free).
2Architecture Diagram
+------------------------------------+ High Memory (0xFFFFFFFF) | Stack (Grows Downwards) | Local stack frames | | | | v | | | | ^ | | | | | Heap (Grows Upwards - malloc/free) | Dynamic memory +------------------------------------+ | BSS Segment (Uninitialized globals)| Zeroed on start +------------------------------------+ | Data Segment (Initialized globals) | Global/static vars +------------------------------------+ | Text Segment (Machine Code) | Read-only instructions +------------------------------------+ Low Memory (0x00000000)
3Code Example
Stage 0 Language Foundations
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int num_elements = 4;
// Allocate zero-initialized memory on Heap
int *arr = (int *)calloc(num_elements, sizeof(int));
if (arr == NULL) {
fprintf(stderr, "Memory allocation failed!\n");
return EXIT_FAILURE;
}
for (int i = 0; i < num_elements; i++) {
arr[i] = (i + 1) * 10;
printf("arr[%d] = %d (at address %p)\n", i, arr[i], (void*)&arr[i]);
}
// Resize heap memory to hold 6 elements
int *temp = (int *)realloc(arr, 6 * sizeof(int));
if (temp == NULL) {
free(arr);
return EXIT_FAILURE;
}
arr = temp;
arr[4] = 50; arr[5] = 60;
printf("After realloc, arr[5] = %d\n", arr[5]);
// Mandatory cleanup
free(arr);
arr = NULL; // Prevent dangling pointer
return EXIT_SUCCESS;
}4Expected Output
arr[0] = 10 (at address 0x1a2b00) arr[1] = 20 (at address 0x1a2b04) arr[2] = 30 (at address 0x1a2b08) arr[3] = 40 (at address 0x1a2b0c) After realloc, arr[5] = 60
5Key Takeaways
- ✓Always check if malloc/calloc returned NULL before dereferencing.
- ✓Always set pointer to NULL after calling free(ptr).
- ✓Every malloc/calloc call must have exactly one corresponding free() call.