This is meant to be a short note on Rust's ownership and borrowing principles, and how they prevent the most common memory bugs from happening.
Stack and Heap
Before diving into memory management, we will quickly recall how the stack and heap work.
The stack and heap are parts of memory available at runtime, structured differently.
To push data onto the stack, data size must be known at compile time.
Data with an unknown size or a size that might change must be allocated on the heap, with a pointer to its heap address pushed onto the stack.
Ownership applies to all Rust values, but it's most visible with heap-allocated data, since Rust must know exactly when to free the heap allocations.
Ownership
Rust has three fundamental ownership rules, which govern how memory is managed:
- A value must have an owner
- A value must only have one owner
- When the owner goes out of scope, the value is dropped
fn main() {
let p = String::new();
let q = p; // owner is now q
} // q out of scope, value dropped
Single ownership makes the responsibility of freeing memory very clear, since multiple owners trying to free the same memory allocation is unsafe.
References and Borrowing
References allow callers to borrow data without taking ownership.
Due to non-lexical lifetimes, a borrow ends at its last use instead of at the end of its surrounding lexical scope.
The following are the rules of references that prevent common memory bugs from happening.
1. Either one mutable reference or multiple immutable references can exist for a value
This avoids aliasing bugs where one part of the code assumes a value is stable, while another part changes it underneath. Across threads, the single mutable reference rule also helps prevent data races.
2. References must always point to valid data
fn main() {
let r;
{
let g = 2;
r = &g; // compiler throws, since r outlives g
}
println!("{}", r);
}
This check prevents dangling pointers from being accessed, as the compiler rejects references that outlive their owner.
Conclusion
To sum it all up, we briefly talked about the stack and heap, covered the fundamentals of ownership and borrowing, and reasoned about how these rules can help mitigate common memory issues.