Process Memory Layout

A running C program’s virtual address space has five regions:

RegionContentsTypical address (x86-64 Linux)
StackLocal variables, function args, return addressesNear 0x7fff... (high)
Heapmalloc/free allocationsMid-range (0x5...0x7f...)
BSSZero-initialized globals (int x;)Low (0x40...0x60...)
DataInitialized globals (int x = 5;)Adjacent to BSS
TextMachine code + string literals (read-only)Lowest

Key Rules

  • Stack grows downward (toward lower addresses on x86). Outer frames have higher addresses than inner frames.
  • Heap grows upward (toward higher addresses). Each malloc may call brk/mmap if the allocator has no free block.
  • String literals ("hello") live in the text/rodata segment — read-only. Writing to them is undefined behaviour and typically causes SIGSEGV.
  • BSS variables are zero-initialized before main runs. Data variables are initialized to their specified value. Both persist for the full lifetime of the process.

Diagnostic: identifying a pointer’s region

From the address alone you can identify which region a pointer belongs to:

printf("stack: %p\n", (void*)&local);      /* 0x7fff... */
printf("heap:  %p\n", (void*)malloc(1));   /* 0x55...   */
printf("text:  %p\n", (void*)main);        /* 0x40...   */
printf("lit:   %p\n", (void*)"hello");     /* 0x40...   same range as text */

This pattern is consistent across Linux processes and is a practical first step when debugging an unexpected crash — the address tells you which allocator or scope owns the memory.

Stack Overflow

The stack has a fixed limit (~8 MB on Linux, set by ulimit -s). Infinite recursion or very large stack allocations exhaust it. The OS signals SIGSEGV when the stack pointer crosses into an unmapped guard page.

Relationship to Debugging Tools

  • Valgrind and ASan track heap allocations and flag out-of-bounds accesses and use-after-free — they only monitor heap memory.
  • GDB can inspect variables in any region via print and x/Nxb addr.
  • The /proc/<pid>/maps file shows the exact layout of a running process including library segments and anonymous mmap regions.

Appears In

m01-c-is-not-java, m02-pointers-memory-model, m03-dynamic-memory