paint-brush
A Simplified Comparison: Rust and Pointersby@uknowwhoab1r

A Simplified Comparison: Rust and Pointers

by @uKnowWhoDevSeptember 9th, 2024
Read on Terminal Reader
tldt arrow

Too Long; Didn't Read

Rust offers a novel approach to guaranteeing strict memory safety and allowing access to low-level memory manipulation. We will examine the similarities and differences between Rust pointers and ownership, borrowing, references, smart pointers, and designing secure, effective code. Rust enforces strict borrowing rules: Multiple**immutable references** are allowed simultaneously. Only one mutable reference** is allowed at a time.
featured image - A Simplified Comparison: Rust and Pointers
@uKnowWhoDev HackerNoon profile picture

In systems programming, memory management is a powerful tool. Traditional languages like C and C++ allow direct manipulation of memory through offering raw pointers. However, significant risks such as, memory leaks, dangling pointers and race coditions in concurrent programs surfaces with this freedom.


Here, Rust adopts a novel approach by guaranteeing strict memory safety and allowing access to low-level memory manipulation. Together, we will examine the similarities and differences between Rust pointers and ownership, borrowing, references, smart pointers, and designing secure, effective code.

What Are Pointers ?

Pointers in programming are like addresses for data in computer memory. Think of memory as a big apartment building:

a. A pointer is like knowing an apartment number.

b. In Rust, references(& and &mut) are like temporary keys to visit an apartment.

c. Smart pointers(unique_ptr<Song>) are like building managers who control access to apartments.


Rust’s system is strict, like a well-run building. It prevents problems like entering a vacant apartment or two people trying to redecorate the same room at once. This keeps everything safe and organized.

Ownership and Borrowing: The Foundation of Rust’s Memory Safety

Ownership is a core concept in Rust, ensuring that only one owner is responsible for a piece of memory at any given time. When memory is no longer used, it is automatically cleaned up.


  • Borrowing allows other parts of the program to temporarily access a value without taking ownership of it. Rust’s borrowing model uses references to either:
  • Read a value through an immutable reference (&).
  • Modify a value through a mutable reference (&mut).


Rust enforces strict borrowing rules:

  1. Multiple immutable references are allowed simultaneously.
  2. Only one mutable reference is allowed at a time.


This ensures that mutable access to data is always safe and eliminates data races in concurrent programming.

a) Immutable References (&T)

An immutable reference (&T) allows borrowing without changing the value. This is crucial for scenarios where multiple parts of a program need to read data simultaneously without modifying it.

Code Approach

Code Approach

fn main() {
    let a= 5;
    let b= &a; // Borrowing aimmutably
    println!("{}", b); // Accessing the value via reference
}

B) Mutable References (&mut T)

mutable reference (&mut T) allows exclusive modification access to a variable. Rust enforces that only one mutable reference can exist at any point in time to avoid data races and inconsistent memory states.

Code Approach

fn main() {
    let mut x = 5;
    let y = &mut x; // Borrowing x mutably
    *y += 1; // Dereferencing and modifying the value
    println!("{}", y);
}

C) Smart Pointers in Rust

In Rust , basic pointer capabilities are extended by smart pointers such as, automatic memory management and reference counting.

  • Box<T>: A special delivery service that takes your item and puts it in a box in the storage room (heap). You get a receipt (pointer) to find it later.
  • Rc<T>: A box that can have multiple receipts**(owner)**. Like a shared storage unit where multiple people have keys.
  • RefCell<T>: Box with a special lock that checks borrowing rules at runtime. Like a safety deposit box that logs who accesses it and how.

D) Lifetimes: Ensuring Valid References

Lifetimes are a key feature in Rust’s memory safety model. Lifetime refers that this reference is valid from this point to that point in time. Rust ensures that references do not outlive the data (compile-time only )they point to, preventing dangling references.

Code Approach

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let string1 = String::from("long string");
    let string2 = "short";
    
    let result = longest(&string1, string2);
    println!("The longest string is: {}", result);
}


In this example:

  • string1 are passed as references to longest.
  • The function checks which string is longer and returns the longer one.
  • Since both string1 and string2 live until the end of main, their lifetimes are long enough for the returned reference to be valid.


Consequently, by detecting problems like dangling pointers and race situations at compile time, Rust’s ownership model, smart pointers, and lifetimes offer a special combination of low-level control and high-level safety, guaranteeing quick, secure, and concurrent programming. Strict reference and borrowing guidelines maximize efficiency without sacrificing security.


All things considered, Rust is an excellent option for systems development, enabling programmers to create effective, dependable, and high-performing code.

References


Don’t forget to read my other posts :