Memory Layout — where things live - MarekBykowski/readme GitHub Wiki
High address
┌─────────────────┐
│ stack │ local vars, function args, return addr — grows DOWN
│ ↓ │ fixed size (usually 8MB on Linux), overflow = segfault
├─────────────────┤
│ (gap) │
│ ↑ │
│ heap │ malloc/free — grows UP, you manage it manually
├─────────────────┤
│ BSS │ uninitialised globals & statics → zero-initialised by OS
├─────────────────┤
│ data │ initialised globals & statics (e.g. int x = 42;)
├─────────────────┤
│ text (code) │ executable instructions — read-only
└─────────────────┘
Low address
int g_init = 42; // data segment
int g_uninit; // BSS — zeroed automatically
void foo() {
int local = 1; // stack
int *p = malloc(4); // p on stack, *p on heap
static int s = 0; // BSS (uninit static) or data (init static)
}
💡 In embedded (no OS): BSS is zeroed by startup code (crt0), heap may not exist at all — everything on stack or statically allocated.
🗑️ malloc / free — and what goes wrong
// Basic usage
int *p = malloc(sizeof(int) * 10);
if (!p) { /* always check! malloc returns NULL on failure */ }
memset(p, 0, sizeof(int) * 10); // heap memory is NOT zeroed
free(p);
p = NULL; // good habit — prevents use-after-free
// calloc — allocates AND zeroes
int *p2 = calloc(10, sizeof(int));
// realloc — resize existing allocation
p2 = realloc(p2, 20 * sizeof(int)); // may move the block!
| Bug | What happens | How to detect |
|---|---|---|
| Memory leak | malloc without free — heap grows until OOM |
Valgrind, AddressSanitizer |
| Double-free | free(p); free(p); → UB, heap corruption |
ASan, guard pages |
| Use-after-free | access *p after free(p) → UB, stale data or crash |
ASan |
| Buffer overflow | write past end of malloc'd block → heap corruption | ASan, bounds checking |
| NULL deref | skipping the if (!p) check → crash |
code review |
// Safe pattern
void *safe_malloc(size_t n) {
void *p = malloc(n);
if (!p) { perror("malloc"); exit(EXIT_FAILURE); }
return p;
}
⚠️ In embedded: avoid dynamic allocation entirely if possible. Heap fragmentation on a microcontroller with 64KB RAM can cause allocation failures hours into a flight.