Question bank — Memory layout — text, data, BSS, heap, stack segments
Vocabulary you need before the traps
Some traps below lean on low-level Unix terms. Define them once here so nothing on the page is used before it is built.
The picture you are drilling against
Before the traps, fix the layout in your eye. This is the virtual address space one process sees — a tall column of bytes, lowest address at the bottom, highest at the top. Figure 1 is the full map, including the read-only rodata section and the kernel region at the very top.

Figure 1 — Full user address space (low → high). Text, rodata, Data, BSS, the
brkheap, the sharedmmap/library region, the stack, and the kernel band at the very top that user code cannot touch.
Figure 2 captures the one dynamic idea the whole page hinges on: heap and stack expand into a shared gap from opposite ends, where the small brk heap sits, and where large mmap blocks actually land.

Figure 2 — Heap vs stack growing into one shared gap. The program break rises from below, the stack pointer falls from above,
mmapblocks land off to the side, and the guard page marks the point where a collision becomes a crash.
True or false — justify
An uninitialized global int g; contains garbage until you assign it.
A global int x = 0; lives in the Data segment because you wrote an initializer.
= 0 is still all-zero information, so the compiler places it in BSS, not Data; only non-zero initializers force Data.BSS uses less RAM at runtime than Data.
The Text segment is read-only so viruses cannot inject code into a running program.
W^X (write XOR execute; see vocabulary box) Text pages are executable-not-writable, so overwriting your own instructions faults; but attackers can still hijack control flow to redirect execution elsewhere (see Buffer overflow and stack smashing).The heap and stack each have a fixed, pre-assigned size boundary between them.
static int s = 0; inside a function lives on the stack because it is declared locally.
static gives static storage duration, so s lives in BSS (zero init) and persists across calls; only its scope is local.Two processes running the same program share one copy of the Text segment.
mmapped and shared the same way.Successive malloc calls always return higher addresses than the previous one.
mmap-backed large allocations can hand back lower or scattered addresses.A pointer returned by malloc is destroyed when the function that called malloc returns.
Stack overflow and running out of heap are the same "out of memory" condition.
malloc returning NULL. Different segments, different symptoms.The kernel lives somewhere in the middle of your program's address space.
Spot the error
"Uninitialized globals are unpredictable, so I always initialize them to zero to be safe."
= 0 doesn't move it to Data anyway. The habit isn't harmful, but the reasoning (that it was unsafe) is wrong."I made a huge int buf[1000000]; global, so my executable file grew by 4 MB."
"To keep memory after the function returns, I declared the array static inside the function."
"My program crashed with stack overflow, so I called free() to release stack space."
free only releases heap blocks and does nothing to the stack. Stack frames are reclaimed automatically on return; the fix is less recursion depth or smaller locals, not free."I returned &local from a function and the caller used it fine, so returning stack addresses works."
local is on the stack and its frame is gone after return, so the pointer is dangling (see Pointers and dangling pointers); the memory may be overwritten anytime."char *msg = "hello"; — I can safely do msg[0] = 'H'."
Why questions
Why split globals into two segments (Data and BSS) instead of one?
Why does the stack grow down (toward lower addresses) while the heap grows up?
Why is stack memory freed automatically but heap memory is not?
free.Why is the Text segment kept separate and marked read-only?
W^X the MMU marks those pages non-writable so accidental or malicious writes to instructions fault (see Virtual memory and paging).Why do local variables often show much higher addresses than malloced blocks?
brk heap grows up from low addresses above BSS, so a snapshot usually shows stack addresses far above heap ones.Why does the C standard guarantee zero for statics but not for locals?
Why are shared libraries mmapped rather than copied into each program?
mmapping a library read-only lets every process map the same physical pages, so one copy of libc serves them all — the same sharing trick as the Text segment.Edge cases
A global array declared but never used: does it still consume RAM at runtime?
int *p = malloc(0); — where does anything live, and is p usable?
p itself lives on the stack, but any bytes malloc reserves come from the heap; malloc(0) may return NULL or a unique non-dereferenceable pointer, so reading/writing through it is undefined — only free(p) is safe.A recursion with no base case: which segment fills up and what happens?
Can the heap ever occupy a lower address than part of the Data/BSS region?
brk heap begins just above BSS as the program break rises; but large allocations via mmap land elsewhere in the middle, so the "always above BSS" rule holds only for the brk-based heap.You free(p) then read *p. Which segment is involved and why is it dangerous?
p is dangling; the bytes may be reused or scrambled at any moment (see Pointers and dangling pointers).A static const int table[] = {1,2,3}; — Data or BSS or something else?
const it typically lands in the read-only rodata section rather than writable Data.Can user code read the kernel-space addresses at the top of the map?
Connections
- Static and global variables — storage duration — the Data-vs-BSS decision rules.
- malloc, calloc, realloc and free — heap lifetime and the traps above.
- Pointers and dangling pointers — the returning-stack-address and use-after-free traps.
- Stack frames and the calling convention — why the stack self-cleans.
- Virtual memory and paging — pages, permissions,
mmapand the kernel split. - Buffer overflow and stack smashing — why read-only Text isn't full protection.