High addresses (0x7fff... for 64-bit architecture)
┌──────────────────┐
│ Kernel Space │ ← OS kernel (not accessible)
├──────────────────┤
│ Stack │ 1. Stack (grows DOWN)
│ ↓ │
│ │
│ (unmapped) │
│ │
│ ↑ │
│ Heap │ 2. Heap (grows UP)
├──────────────────┤ ← program break
│ .bss │ 3. Uninitialized data (zero-init globals)
├──────────────────┤
│ .data │ 4. Initialized data (mutable globals/statics)
├──────────────────┤
│ .rodata │ 5. Read-only data (string literals, consts)
├──────────────────┤
│ .text │ 6. Code (executable instructions)
├──────────────────┤
│ (reserved) │
└──────────────────┘
Low addresses (0x0000...)
In the binary file (ELF):
- Section =
.text,.rodata,.data,.bss - Stored in the executable file on disk, and is loaded before the heap segment starting at the low address.
In memory (running process):
- Segment = mapped sections
- OS loads sections into memory segments
static GLOBAL: i32 = 42;
fn main() {
let stack_var = 5;
let heap_var = Box::new(10);
println!("Code (.text): {:p}", main as *const ());
println!("RO data: {:p}", "literal");
println!("Data (.data): {:p}", &GLOBAL);
println!("Heap: {:p}", heap_var);
println!("Stack: {:p}", &stack_var);
}