This README wraps up the most important concepts inside chapter 4 of the Rust Book.
Inside the src
folder are put correspondent examples (work in progress).
Sources 4.1 What Is Ownership? 4.2 References and Borrowing 4.3 Fixing Ownership Errors
-
use-after-free → it's possible to have a pointer to freed memory but → it's not permitted to use it (W)
let my_vector = vec![1,2]; let pointer_1 = &my_vector[0]; my_vector.push(3); //pointer_1 has been freed println!("{pointer_1}");
-
double-free → pointer used after its data its freed → moving out of a reference
let my_vector = vec![1,2]; let pointer_1 = &my_vector[0]; let first_element = *pointer_1; drop(first_element); // vec![1,2] is also freed drop(my_vector); //error! vec![1,2] was already freed
-
- memory corruption (70%)
- it's a mapping of variables-values inside a single function (scope)
- after a function returns, the frame is deallocated -or freed or dropped
- contains list of frames of currently-called-functions
- LIFO (popped off)
- heap data can persist beyond the scope of a single function call → it can be moved, shared, and referenced by different parts of the program. It's deallocated when there are no more reference to it.
- hosts 2 types of pointers:
- Boxes (pointers owning data on the Heap)
- are constructs used by collections (Vec, String, HashMap)
let box = Box::new(1) //box is a pointer let pointer_to_box = box; //copying a pointer // pointer_to_box is another pointer to 1 // box has been moved
- references to the stack
let ref_box_stack = &box
- references to the heap
let ref_content_box_heap = &*box
- Boxes (pointers owning data on the Heap)
push
reallocates vector data
- e.g.
let pointer_to_the_heap = String::from("heap_string");
or&v[2]
:- Non-owning pointer → it just borrows a variable's data
- Pointer Safety Principles
- data should not be aliased (R) and mutated (W) at the same time
- do not use any reference to a data, while another reference to the same data it's still alive
- slices
- IMMUTABLE REFERENCE (&)
-
let a = String::from("x")`; let b = &a;
- the variable that hold the reference
b
has only (R) permission and creates temporary aliasing → accessing data through different variables - it temporary removes WO (moving and borrowing) F permissions to the referenced data
a
*b
until the variable that holds the referenceb
it's no longer alive (deallocation) →
-
- MUTABLE (UNIQUE) REFERENCE (&mut)
-
let a = String::from("x")`; let b = &mut a;
- only one for each scope
- the variable that holds the reference
b
has (RW) permissions on datax
- it temporary removes RWO (moving and borrowing) F permissions to the referenced data
a
*b
until the variable that holds the referenceb
it's no longer alive (deallocation) → avoids undefined behaviour
-
- deallocation is automatically managed by
rustc
- when a variable on the Stack owns a Box and is deallocated,
the Box:
- is also deallocated from the Heap
- is returned from borrowing
Permissions are lost after a path|variable is not longer in use
- data can be copied to another location
- enabled by default
- data can be mutated in-place
- not enabled by default
-
enabled by default
-
variables can OWN a data on the Heap (e.g. Box)
let x = Box::new(1) //x owns the Box
-
it can be MOVED from a variable
a
to another variableb
,rustc
looks at the whole type signature → different tuple type fields are considered just one type field
-
variable
a
can be passed as parameterb
to a function:let a = String::from("heap_string_here"); //a is a POINTER to the heap let c = add_some_stuff(a); //moving of ownership happening here: ownership is moved from a to b and a is freed! //! cannot access {a} anymore: the pointer lost his connection to the heap fn add_some_stuff(mut b:String) -> String{ b.push("_stuff") b }
-
variable
a
can be assigned to the variableb
:let a = Box:new(1); let b = a; //moving of ownership happening here: ownership is moved from a to b. A gets deallocated when not in use
-
m. data
x
out of a referencea
intob
let a = x; let b = *a;
- the variable
a
, that has lost ownership (it was freed), cannot be used after the moving of ownership - moving of ownership can be avoided using
.clone
→ it creates deep copies inside the heap - moving: Boxes and String (that do not implement Copy), when moved, are removed by all their permissions (RWO) (see HEAP)
-
it can be DROPPED with
drop()
- checks safety of input/output references, that are treated differently than references within a function body
- returning a reference to a function's local variable is not possible
- passing immutable &ref as param and want to edit its content
- using a reference while its data has been previously dropped by a function or taken by an alias
- modifying array content i32 vs String
- borrowing one element of the array and tuples
- The borrow checker sometimes rejects programs that have defined behaviour → it does not check the content of variables or functions
- tuple