The Virtual Address Space: Text, Data, BSS, Heap, Stack
What This Concept Is
When a process runs, the operating system gives it a private virtual address space. Not all of that range is usable; the OS lays out a handful of named regions, each with its own purpose and lifetime:
- text (also
.text): the program's machine code. Read-only and executable. - rodata (
.rodata): read-only constants such as string literals andconstglobals. - data (
.data): initialized writable globals andstaticvariables. - bss (
.bss): zero-initialized writable globals andstaticvariables. Takes zero space in the binary; the OS fills it with zeros at load time. - heap: dynamically allocated memory (
malloc/free). Grows upward (toward higher addresses) on most systems. - stack: per-thread call stack for local variables, arguments, return addresses. Grows downward on most systems.
Why It Matters Here
The segment a variable lives in determines:
- how long it lives (function call, program run, or until
free) - whether you can write to it (writing to
.rodatatraps) - whether its address is predictable (stack is not;
.dataoften is) - who is responsible for releasing it (heap requires an explicit
free)
Debuggers, profilers, and linkers all speak in these segment names.
Concrete Example
Typical Linux 64-bit layout, high to low:
high addresses
+----------------------+
| (kernel, not shown) |
+----------------------+
| Stack (grows down) | locals, saved rbp, return addresses
| | |
| v |
+----------------------+
| (unmapped gap) |
+----------------------+
| Memory-mapped region | shared libraries, mmap'd files
+----------------------+
| (unmapped gap) |
+----------------------+
| ^ |
| | |
| Heap (grows up) | malloc'd blocks
+----------------------+
| .bss (zeroed) | uninitialized globals and static
+----------------------+
| .data (writable) | initialized globals and static
+----------------------+
| .rodata (read only) | string literals, const
+----------------------+
| .text (executable) | machine code
+----------------------+
low addresses
A tiny C program placing a variable in each segment:
#include <stdlib.h>
const char *msg = "hi"; /* msg in .data; "hi" in .rodata */
int g_init = 7; /* .data */
int g_zero; /* .bss */
int main(void) {
static int s = 3; /* .data */
int local = 1; /* stack */
int *heap = malloc(sizeof *heap); /* heap */
(void)msg; (void)g_init; (void)g_zero; (void)s; (void)local;
free(heap);
return 0;
}
Common Confusion / Misconception
"The heap and stack are next to each other." On modern 64-bit systems they are separated by a huge unmapped region. The old "the heap grows until it meets the stack" image is simplified history.
"String literals are on the stack." No. char *s = "hello"; places the string in .rodata and s on the stack. Writing s[0] = 'H'; is undefined behavior. In contrast, char s[] = "hello"; copies it into a stack-allocated array that is writable.
"Globals are on the heap because they outlive functions." Globals are in .data or .bss. The heap is strictly what malloc returns.
How To Use It
For every variable in a program:
- Ask: where is it stored? stack, heap,
.data,.bss, or.rodata? - Ask: who owns it? (caller's frame, this function's frame, the whole process)
- Ask: when is it freed? (automatic on function return, explicit
free, or program exit) - If you need its address to survive the function, it cannot be on the stack.
Check Yourself
- Why is
return &local;a bug? - What is the difference between
static int x = 0;andint x = 0;inside a function? - Where does a string literal
"hello"live, and why can you not modify it?
Mini Drill or Application
#include <stdio.h>
#include <stdlib.h>
int g_init = 7;
int g_zero;
int main(void) {
int local = 1;
int *heap = malloc(sizeof *heap);
*heap = 2;
printf("g_init=%p g_zero=%p\n", (void *)&g_init, (void *)&g_zero);
printf("main =%p local =%p heap =%p\n",
(void *)&main, (void *)&local, (void *)heap);
free(heap);
return 0;
}
Build: gcc -Wall -Wextra -o segments segments.c. Run it twice. The stack and heap addresses may change between runs because of address-space layout randomization; the .data / .text addresses stay similar.