Foundations
Values, variables and pointers
Values in Rust are a combination of a type and an element in the domain of that type.
Values are stored at a place which can be the stack, the heap or any other location.
A pointer points to such a place. It holds the address of a region of memory.
The most common way to store a value is on a named value slot on the stack. We refer to this named value slot by a variable.
Note: We can store the same pointer in more than one variable and thus have multiple variables that indirectly refer to the same location in memory, and thus the same underlying value.
High level model of variables
In a high level model of a variable, we can think of variables as name given to a value. When we assign a value to a variable, then that value from then on is named by that variable.
A good mental model is to imagine a dependency relationship being created between two successive access of a variable. When a variable is moved, no dependency can be mapped to it. A dependency relationship cannot be mapped from a variable that isn’t there(hasn’t been initliazed or has been moved).
The dependency relationships or flows trace the lifetimes of a particular instance of a value.
This roughly matches roughly how the compiler and the borrow checker reason about the program.
Low level model of variables
Variables name memory locations that may or may not hold legal values.
let x: u32; // x is a name for a region in memory
= 6; // value 6 written to address x
If we declare multiple variables with the same names they end up at different memory locations.
Memory regions
Stack
Stack is a region of memory that is used by a program as a scratch space for function calls. Every time a function is called a new ‘frame’ is allocated on top of the stack. It contains all the variables within the function along with the arguments the function takes. A variable stored on the frame cannot be accessed after the frame goes away(lifetime is lifetime of the frame).
Heap
Heap is a pool of memory that isn’t tied to the stack of the program. This is useful when we want a value to live beyond the frame of the current function’s frame.
Since allocations from the heap do not go away after the function, we can allocate in one function pass around the pointer to another thread and continue to safely operate of the value in the heap. The pointer has an unconstrained lifetime - its lifetime is however long the program keeps it alive.
Static Memory
Static memory is a catch all term for several closely related regions located in the file a program is compiled into. Values in static memory live for the duration of the program.
Static memory also holds the variables we define with a static
keyword as well as certain constants values like strings.
The 'static
lifetime does not create a static variable but once a reference with a static lifetime is created, it lives on till the end of the program. Whereever it pionts to might as well be in the static memory.