- Data can be stored either in stack or heap memory in Rust.
Memory Types
- Stack Memory
- Heap Memory
Stack and Heap
Stack
It collects values in the order it get them and removes the values in the opposite order. Referred to as Last In, First Out (LIFO).
Stack: Think of a stack of plates
- Adding data is called pushing onto the stack,
- Removing data is called popping off the stack.
- Stack memory is an organized memory.
- It is faster than the heap memory due to the way it accesses the memory.
- All data gathered on the stack must have a known, fixed size
Stack Push and Pop Example:
Stack: in action
Stack: How it works?
The code then calls a function, the values move into the function (including, potentially, pointers to data on the heap) and the function’s local variables get pushed onto the stack.
When the function ends, those values get popped off the stack.
- The Heap is Less Organized.
- Requested from OS.
- Slower.
- Follow pointer.
- The huge amount…take time to manage data in the heap.
- The Data with a size that is unknown at compile time or size that might change must be kept on the heap.
Heap: Allocation
- When we put data on the heap, we say for some amount of space from OS.
- The operating system gets an empty spot in the heap that is big enough, marks it as being in use, and returns a pointer, which is the address of that location.
Because the operating system has not had to search for a place to store new data; that location is always at the top of the stack.
Why accessing data to the heap is slower than allocating on the stack?
Allocating space on the heap needs more work because you ask for some amount of space to operate the system every time. OS has to follow the pointer every time.
Ownership
- All programs have to find the way they use a computer’s memory while running.
- Some languages have kept garbage collection that constantly looks for no longer used memory as the program runs.
- The programmer must explicitly allocate and free the memory in other languages.
- Rust uses a third approach wherein memory is kept through a system of ownership.
- Ownership is managed with a set of defined rules that the compiler checks at compile time.
- Ownership is the forwarding of a currently possessed entity to another party which causes the previous owner to no longer have access to the object that is being transferred.
- There are very clear rules about which piece of code owns a resource in Rust.
- It’s the block of code that created the object representing the resource in the simplest case.
- In the last of the block, the object is destroyed and the resource is released.No one of the ownership features slows down our program while it’s running.
Example
fn main() {// s is not valid here, it’s not yet declared let s = "hello"; // s is valid from this point forward // do stuff with s println!("{}", s); }//
This scope is finished, and s is no longer valid
In this example, the letter or variable “s” is the owner of the word “hello” and is valid from the point of declaration after the start of the parenthesis “{“
and it exists valid until the end of the parenthesis “}”.
Why Ownership
- Maintaining a record of what parts of code are using what data on the heap, minimizing the amount of duplicate data on the heap, and cleaning up unused data on the heap for that we don’t run out of space are all problems that ownership addresses.
- All primitive data types (integers, booleans, string literals) and pointers (address of heap data) are stored and kept on a stack whereas for more complicated data types we have a heap.
Ownership Rules
let a = “Hello world!”;
↙ ↘
Variable Value
In this example, the variable i.e “a” is also the owner of the value “Hello world!”.
Rule # 2
There must only be one owner at a time
Example
let b = String::from(“Hello”); –> here variable “b” is the owner
let c = d; –> here the value of “c” is moved to variable “d” which now becomes the owner of “Hello”
Understanding both variables “a” and “b” are within the same scope.
Rule # 3
When the owner went out of scope, so does the value
Example
fn main() { { –> “b” is not valid here, it’s not yet declared let a = “Hello"; –> “b” is valid from this point forward –> do stuff with “b” } –> this scope is now over and “b” is no longer valid }
For more detail click