memtrace

Memory regions

  • Stack Memory
  • Heap Memory
  • Static Memory

Ownership model

  • Ownership & Moves
  • Borrowing & References
Open the Playground
VisualizersOwnership & Moves

Ownership & Moves

How ownership of a Vec moves between variables and into a function, and who frees 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 a = vec![1, 2, 3];
3 let b = a;
4 take(b);
5}
6
7fn take(v: Vec<i32>) {
8 println!("{}", v.len());
9}

Ownership & Moves

How ownership of a Vec moves between variables and into a function, and who frees it

HIGH ADDRESSESStackframes and localsHeapBox, String, Vec dataStatic datastatics, string literalsCodecompiled machine codeLOW ADDRESSES
Where this lives in a running program
STACKHEAPamovedbownerVec[1, 2, 3]MOVE
The idea in one picture

Step by step

Key takeaways

  • Every value has exactly one owner
  • Assigning or passing a non-Copy value moves its ownership
  • A moved-from variable can't be used again
  • The value is dropped exactly once, by its final owner

Resources

  • The Rust Book: What is ownership?The ownership rules and the move diagrams this example is based on
  • Error code E0382The use-after-move error, with fixes
  • std::ops::DropWhat happens when an owner goes out of scope

Research notes

  • A move is a shallow copy of the stack bytes plus the compiler forbidding the old name, and the optimiser often removes even that copy
  • Calling .clone() deep-copies the heap data when you really need two independent owners
  • Rc<T> and Arc<T> allow shared ownership by counting references instead
stdoutempty

$cargorun// waiting for the first println!

Auto-play steps