0% found this document useful (0 votes)
4 views22 pages

Rust 2

The document explains Rust's ownership system, which ensures memory safety by tracking variable ownership and automatically freeing memory when it goes out of scope. It distinguishes between stack and heap memory allocation, highlighting how values are stored and accessed differently in each. Additionally, it covers ownership rules, references, borrowing, and the use of slices in Rust, emphasizing the importance of ownership in memory management.

Uploaded by

Cloud Computing
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views22 pages

Rust 2

The document explains Rust's ownership system, which ensures memory safety by tracking variable ownership and automatically freeing memory when it goes out of scope. It distinguishes between stack and heap memory allocation, highlighting how values are stored and accessed differently in each. Additionally, it covers ownership rules, references, borrowing, and the use of slices in Rust, emphasizing the importance of ownership in memory management.

Uploaded by

Cloud Computing
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 22

RUST-2

On Rust ownership
• In Rust, ownership is a system the compiler uses to ensure memory safety.
• It manages ownership by keeping track of which variables own which values, and making sure that those
values are only dropped when they are no longer being used.
• Rust guarantees memory safety with a feature called ownership.
• memory management is handled by the Rust compiler using the ownership model.
• A Rust compiler will automatically insert a drop statement to free the memory. It uses the ownership model
to decide where to free memory; when the owner goes out of scope, the memory is freed.
• When doing assignments (let x = y) or passing function arguments by value (foo(x)), the ownership of the
resources is transferred. In Rust-speak, this is known as a move.

Key points about ownership in Rust:

• Every value in Rust has a single owner.


• When the owner goes out of scope, the value is dropped.
• Ownership can be transferred from one variable to another using assignment (e.g., let x = y).
• When a value is transferred, the previous owner no longer has access to the value.
fn main(){

let x =5;

// x is dropped here since it goes out of the scope

}
What are the stack and the
heap?
• The stack and heap are both memory storage segments that are available for your code to use at runtime.
• Rust is a system programming language, how values are stored (in the stack or heap) is essential to how the language
behaves.

How memory is stored in a stack:

These books are arranged in a way that the last book is placed on top of the stack and the first book is at the bottom.
Ideally, we wouldn’t want to slide the bottom book out from under the stack, it would be easier to pick a book on top of
to read.

This is exactly how memory is stored in the stack it uses the last in, first out method.

it stores values in the order it gets them but removes them in the opposite order. It’s also important to note that all data
stored in the stack have a known size at compile time.
What are the stack and the
heap?
• Memory allocation in the heap:

Think of going to buy a shirt for a friend. You don’t know the exact size shirt your friend wears,
but seeing him frequently, you think he might be a medium or large. While you aren’t completely
sure, you buy the large because he will still be able to physically fit into it, even if he’s a medium.
This is how memory allocation in the heap works.

When you have a value (your friend) for which you don’t know the exact amount of memory it
will require (size of t-shirt), you request for a specific amount of space for the value. The
allocator finds a spot in the heap that is big enough and marks that spot as in use. This is an
important difference between the stack and the heap: we don’t need to know the exact size of
the value being stored in the heap.
• Allocating on the heap involves searching for an empty space big enough to
match the amount of memory you requested, and returning an address to the
location which will be stored in the stack. Retrieving a value from the heap
requires you to follow a pointer to the place where the value is stored in the
heap.

• Allocating on the heap looks like book indexing, where a pointer for a value
stored in the heap is stored in the stack. However, the allocator also needs to
search for an empty space that is big enough to contain the value.

• Local variables of a function are stored on the function stack, whereas data types,
such as String, Vector, Box, etc., are stored on the heap. It is important to
understand the memory management of Rust to ensure the app behaves as
intended.
Ownership rules
• Ownership has three basic rules that predict how memory is stored in the stack and in the heap:

Each Rust value has a variable called its “owner”:


• let x = 5; // x is the owner of the value "5“

Each value can only have one owner at a time .When the owner goes out of the scope, the value will be dropped:

fn main() {
{// scope begins
let s = String::from("hello"); // s comes into scope
}// the value of s is dropped at this point, it is out of scope
}
How ownership works

<// memory allocation in the stack


fn main() {
{ // a is not valid here
let a = 5; // a is valid here
// do stuff with a
}// println!("{}", a)a is no longer valid at this point, it is out of scope
}
Memory allocation in heap
fn main() {
{
let mut s = String::from("hello"); // s is valid from this point forward

s.push_str(", world!"); // push_str() appends a literal to a String

println!("{}", s); // This will print `hello, world!`


}// s is no longer valid here
}

When the variable goes out of scope, the Rust ownership feature allows for the memory to be returned
(freed).
Clone and copy
// stack case
fn main() {
let a = "5";
let b = a; // copy the value a into b
println!("{}", a) // 5
println!("{}", b) // 5
}

//heap case

fn main() {
let a = String::from("hello");
let b = a; // copy the value a into b
println!("{}", a) // This will throw an error because a has been moved or ownership has been transferred
println!("{}", b) // hello
}

heap are stored like an indexing process, where the pointer is stored in the stack
• When you copy a value that is stored
on the heap, the system automatically
copies only the pointer, leaving out the
heap data. Since data can have one
owner, ownership of string is
transferred from a to b.

fn main() {
let a = String::from("hello");
let b = a.clone(); // creates a copy of
data on the heap and return pointer to it

println!("a = {}, b = {}", a, b);// a=hello,


b=hello
}
Ownership in practice
fn main() {
let x = 5;
let y = x;

println!("x = {}, y = {}", x, y);


}

Ownership is managed copying the value, so after assigning x to y you get two variables owning two values (value is 5in our
example).
Example ownership transfer
fn main() {
let x = 5;
let mut y = x;

println!("x = {}, y = {}", x, y);

y = 8;

println!("x = {}, y = {}", x, y);


}

// OUTPUT
x = 5, y = 5
x = 5, y = 8
Why ownership is so important?
• scope is an area of code where a variable “live”.
• A variable defined in a scope isn’t visible outer of that scope.
// stack variable scope example
fn main() {
let a = 3;

// nested scope
{
// Allocate an integer on the heap
let b = 5;
println!("Do something with {b}");
}

// Here 'b' doesn't exist anymore but 'a' does


println!("Do something with {a}");

}
// Here 'a' doesn't exist anymore
Ownership with variables allocated in
the heap
fn main() {
let a = String::from("hello");

// nested scope
{
// Allocate an integer on the heap
let b = String::from("world");
println!("Do something with {b}");
}

// Here 'b' doesn't exist anymore but 'a' does


println!("Do something with {a}");
}
Ownership in Rust
• In Rust the behavior is the same, since it guarantees that there is a single owner
for any specific memory block, it can free the corresponding memory when the
owning variable get out of scope, being sure that no one else is owning the
same memory area.
References and borrowing
• With references, you can use a function that has a reference to an
object as a parameter instead of taking ownership of the value.
• With ampersands (&) you can refer to a value without taking
ownership of it.
fn main() {
let s1 = &givesOwnership(); // moves its return value into s1 that borrows the value

let s2 = String::from("hello"); // s2 comes into scope

let s3 = takesAndGivesBack(s2); // s2 is moved into s3


println!("{}", s1);
println!("{}", s3); // takesAndGivesBack, which moves its return value into s3

} // Here, s3 goes out of scope and is dropped. s2 goes out of scope but was
// moved, so nothing happens. s1 goes out of scope and is dropped.

fn givesOwnership() -> String { // givesOwnership will transfer ownership of its


// return value to the caller of the function

let someString = String::from("hello"); // someString comes into scope

someString // someString is returned and


// moves out to the calling
// function
}

// takesAndGivesBack will take a String and return one


fn takesAndGivesBack(aString: String) -> String { // aString comes
// scope

aString // aString is returned and moves out to the calling function


references

fn main() {
let s1 = String::from("hello");

let len = calculate_length(&s1);

println!("The length of '{}' is {}.", s1, len);


}

fn calculate_length(s: &String) -> usize {


s.len()
}
Slice
• Instead of referencing a whole collection, you can reference elements that are
next to each other in a sequence. To do this, you can use the slice type in Rust.
However, this feature doesn’t have ownership like referencing and borrowing.
fn main() {
let s = String::from("Nigerian");

// &str type
let a = &s[0..4]; // doesn't transfer ownership, but references/borrow the first four letters.
let b = &s[4..8]; // doesn't transfer ownership, but references/borrow the last four letters.
println!("{}", a); // prints Nige
println!("{}", b); // prints rian

let v=vec![1,2,3,4,5,6,7,8];

// &[T] type
let a = &v[0..4]; // doesn't transfer ownership, but references/borrow the first four element.
let b = &v[4..8]; // doesn't transfer ownership, but references/borrow the last four element.
println!("{:?}", a); // prints [1, 2, 3, 4]
println!("{:?}", b); // prints [5, 6, 7, 8]

You might also like