Rust - Ownership Flashcards

1
Q

The memory for a program can be allocated in where?

A

Heap, Stack

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Describe Stack

A

A stack follows a last in first out order.

Stack stores data values for which the size is known at compile time.

For example, a variable of fixed size i32 is a candidate for stack allocation. Its size is known at compile time.

All scalar types can be stored in stack as the size is fixed.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Describe Heap

A

The heap memory stores data values the size of which is unknown at compile time.

It is used to store dynamic data.

Simply put, a heap memory is allocated to data values that may change throughout the life cycle of the program.

The heap is an area in the memory which is less organized when compared to stack.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Rules of ownership

A

Every data stored in rust has an owner
Each data can have only one owner at a time.
Two variables cannot point to the same memory location.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Ways to transfer ownership

A

Assigning value of one variable to another variable.

Passing value to a function.

Returning value from a function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Example of assigning value of one variable to another variable.

A

fn main() {
let v = vec![1,2,3];

// vector v owns the object in heap
let v2 = v; //v passed ownerhsip

println!(“”, v);

//throws an error cuz v no longer has ownership.
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Example of passing value to a function.

A

fn main(){
let v = vec![1,2,3]; // vector v owns the object in heap
let v2 = v; // moves ownership to v2
display(v2); // v2 is moved to display and v2 is invalidated
println!(“In main {:?}”,v2); //v2 is No longer usable here
}
fn display(v:Vec<i32>){
println!("inside display {:?}",v);
}</i32>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Example of returning value from a function.

A

fn main(){
let v = vec![1,2,3]; // vector v owns the object in heap
let v2 = v; // moves ownership to v2
let v2_return = display(v2);
println!(“In main {:?}”,v2_return);
}
fn display(v:Vec<i32>)->Vec<i32> {
// returning same vector
println!("inside display {:?}",v);
}</i32></i32>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What is the relationship with ownership and primitive types

A

In case of primitive types, contents from one variable is copied to another. So, there is no ownership move happening. This is because a primitive variable needs less resources than an object.

fn main(){
let u1 = 10;
let u2 = u1; // u1 value copied(not moved) to u2

println!(“u1 = {}”,u1);
}

//output will be 10

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Manual memory management has been a major source of vulnerability in systems programming. especially 05 development. Discuss the basis of preference for Rust over languages like C/C++ in the quest to mitigate vulnerability risks in your discussion, describe at least twa concrete examples of potential vulnerabilities of concern.

A

Manual memory management, as commonly used in languages like C and C++, has been a significant source of vulnerabilities in systems programming, particularly in security-critical applications.
These vulnerabilities often arise from errors such as buffer overflows, use-after-free bugs, and memory leaks, which can lead to serious security exploits and system compromises.

  1. Ownership and Borrowing: Rust’s ownership system enforces strict rules around memory management at compile time, eliminating many common memory-related vulnerabilities. Every value in Rust has a single owner, and ownership is transferred between scopes through moves. Additionally, Rust’s borrowing mechanism allows for temporary, read-only access to data without transferring ownership.
    This prevents common issues like use-after-free bugs and data races by statically enforcing the lifetime of references.

Example: Example Vulnerability: In C or C++, a use-after-free vulnerability occurs when a program continues to use a pointer to memory that has been deallocated. This can lead to undefined behavior or allow an attacker to execute arbitrary code by controlling the freed memory. With Rust’s ownership system, such vulnerabilities are prevented at compile time, as the compiler ensures that references to freed memory are not used.

  1. Safe Abstractions and Standard Library: Rust provides safe abstractions for common operations, such as strings, collections, and file I/O, through its standard library. These abstractions are designed to prevent common memory-related vulnerabilities by handling memory allocation and deallocation automatically, using safe and predictable patterns.

Example Vulnerability: Buffer overflow vulnerabilities occur when a program writes beyond the boundaries of a buffer, leading to memory corruption and potential code execution exploits. Rust’s standard library provides safe abstractions for string handling, such as String and Vec, which automatically resize themselves as needed and prevent buffer overflows. Additionally, Rust’s iterators and safe indexing operations help prevent off-by-one errors that often lead to buffer overflows in C and C++.

In summary, Rust’s memory safety features, including its ownership system, borrow checker, and standard library abstractions, make it a preferable choice over languages like C and C++ for systems programming tasks where security is a top priority.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How to Declare a variable that can conditionally hold a return value from a function call, ignoring errors if they occur:

A

let result = function_call().ok();

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How to Declare a variable that can conditionally hold a return value from a function call, or an error message if there was an error:

A

let result = match function_call() {
Ok(value) => Some(value),
Err(error) => Some(format!(“Error: {}”, error)),
};

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How Process error message from a function call if an error is returned, otherwise handle a situation where neither value nor error is returned:

A

match function_call() {
Ok(value) => {
// Handle the value
}
Err(error) => {
// Process the error message
println!(“Error: {}”, error);
}
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q
A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly