memtrace

Memory regions

  • Stack Memory
  • Heap Memory
  • Static Memory

Ownership model

  • Ownership & Moves
  • Borrowing & References
Open the Playground
VisualizersHeap Memory

Heap Memory

How Box and Vec put data on the heap, what lives on the stack instead, and how destructors free it

What's happening · 01 / 09

Before anything runs

The compiled program has been loaded into memory, but no function has run yet. Nothing is on the stack and nothing is on the heap

Code

1fn main() {
2 let boxed = Box::new(5);
3 let vector = vec![9, 8, 7];
4 println!("{boxed} {vector:?}");
5}

Heap Memory

How Box and Vec put data on the heap, what lives on the stack instead, and how destructors free it

HIGH ADDRESSESStackframes and localsHeapBox, String, Vec dataStatic datastatics, string literalsCodecompiled machine codeLOW ADDRESSES
Where this lives in a running program
HEAP0x000x080x100x18StringBoxVec<u8>freedIN USEFREE
The idea in one picture

Step by step

Key takeaways

  • The heap data lives elsewhere; the stack only holds a pointer to it
  • A Vec on the stack is three fields: ptr, len and cap
  • Owners free their heap memory in their destructor
  • Locals are dropped in reverse order of declaration

Resources

  • The Rust Book: Using Box<T> to point to data on the heapWhen a single boxed value is useful
  • The Rust Book: Storing lists of values with vectorsCreating, updating and reading a Vec
  • std::vec::Vec, guaranteesWhy a Vec is a (pointer, capacity, length) triple
  • The Rust Reference: DestructorsThe exact order values are dropped in

Research notes

  • A Box<T> for a sized T is a single pointer. Boxes of unsized types such as Box<[T]> or Box<dyn Trait> are fat pointers that also carry a length or a vtable pointer
  • The addresses 0x1234 and 0x2468 are made up. The real allocator picks any free spot, and the addresses change from run to run
  • Vec doesn't promise a growth strategy, only that push is amortised O(1)
stdoutempty

$cargorun// waiting for the first println!

Auto-play steps