Rust Stack and Heap
Every running program stores data in two memory areas: the stack and the heap. Rust ownership rules make sense only after you understand how these areas differ. Think of the stack as a neat pile of plates and the heap as a large warehouse with numbered shelves.
The Stack
The stack stores values in strict order. New items land on top, and the top item leaves first. Programmers call this behavior last in, first out.
Stack grows upward +-----------+ | c = 30 | <-- top (newest) +-----------+ | b = 20 | +-----------+ | a = 10 | <-- bottom (oldest) +-----------+
Each function call receives its own block of stack space called a frame. The frame disappears when the function returns, and the memory becomes free again instantly.
Stack Strengths
- Extremely fast, because the computer only moves one pointer
- No cleanup work is needed
- Values have sizes known at compile time
What Lives on the Stack
Fixed-size types sit on the stack: integers, floats, booleans, characters, tuples of those types, and arrays with a set length.
let count: i32 = 42;
let ready = true;
let point = (3, 4);The Heap
The heap holds data whose size may change or stays unknown until the program runs. A text typed by a user fits this description. The program asks the memory allocator for space, and the allocator returns the address of a free spot.
let mut message = String::from("hello");
message.push_str(" world");The text can grow, so Rust keeps the letters on the heap. The stack keeps a small handle that points to them.
STACK HEAP +------------------+ +---+---+---+---+---+---+---+---+---+---+---+ | message | | h | e | l | l | o | | w | o | r | l | d | | pointer -------+--------> +---+---+---+---+---+---+---+---+---+---+---+ | length = 11 | | capacity = 11+ | +------------------+
Heap Strengths and Costs
The heap offers flexibility. Data can grow, shrink, and outlive the function that created it. The price is speed: the allocator must hunt for a free slot, and the program must follow a pointer to reach the data.
Side-by-Side View
| Feature | Stack | Heap |
|---|---|---|
| Access speed | Very fast | Slower |
| Size rule | Known at compile time | Can change at run time |
| Cleanup | Automatic on function exit | Managed by ownership |
| Typical types | i32, bool, char, arrays | String, Vec, Box |
Why Rust Cares
Languages with manual memory control let programmers forget to free heap memory, or free it twice. Languages with garbage collectors pause the program to hunt for unused data. Rust takes a third path. Each heap value has exactly one owner, and the compiler inserts the cleanup call exactly when the owner leaves scope.
{
let s = String::from("hi"); // heap memory reserved
...use s...
} // heap memory released here
Putting Data on the Heap with Box
A Box moves a single value onto the heap. The stack keeps only the pointer.
fn main() {
let boxed = Box::new(100);
println!("Value: {}", boxed);
}Rust frees the box automatically when boxed goes out of scope.
Seeing the Size Difference
The size_of function reports how many bytes a type occupies on the stack.
use std::mem::size_of;
fn main() {
println!("i32: {} bytes", size_of::<i32>());
println!("String handle: {} bytes", size_of::<String>());
}
i32: 4 bytes String handle: 24 bytes
A String handle always uses 24 bytes on a 64-bit machine, whether the text holds three letters or three million.
Everyday Analogy
A hotel front desk keeps a small card listing your room number. The card is the stack part. The room itself, with the bed and furniture, is the heap part. Losing the card makes the room unreachable, and the hotel needs to clean it. Rust performs that cleanup when the card owner leaves.
Key Points
- The stack stores fixed-size values and runs fast.
- The heap stores flexible data and needs a pointer.
- A
Stringkeeps a handle on the stack and letters on the heap. - Ownership rules free heap memory without a garbage collector.
