Ownership(avoid crash in Rust)

- Rust compiler(rustc) does ownership rules checks at compile time using borrow checker.
- Every Variable/data have single owner at a time. When the owner goes out of scope, Rust automatically deallocates the memory.
- Ownership applies to memory allocated on heap(dynamically), Eg: String(), vector ie those are moved. For variable allocated on Stack (Eg: int, float) variable is copied.
In Rust, raw pointers (*const T and *mut T) don't embody ownership semantics directly. However, smart pointers have ownership like
- Box<T>: It represents ownership of a heap-allocated value.
- Rc<T>: It provides reference counting and allows multiple ownership.
- Arc<T>: It's like Rc<T>, but with atomic reference counting, suitable for concurrent access.

C++ (Crash in C++) Rust (No null pointer Exception(Crash) in Rust)
unique_ptr

#include <iostream>
#include <memory>  // unique_ptr
using namespace std;

int main() {
    // Create a unique_ptr to manage the std::string object
    unique_ptr <string> s = make_unique <string>("hello");

    // Transfer ownership to s1
    unique_ptr < string> s1 = move(s);

    // No compile time check.
    // Run time Segmentation fault
    cout << *s;

    std::cout << *s1;

    return 0;
}
                        

fn main() {
    // Box owns the heap-allocated String
    let s = Box::new(String::from("hello")); 

    // Ownership transferred to s1
    let s1 = s; 

    // Compilation error
    // value borrowed here after move
    // The ownership of the String was moved to s1, 
    //so s is no longer valid to use
    println!("{}", s);
} // Box goes out of scope, 
// and the String is deallocated automatically
                            
                        

Borrow Checker

Borrow Checker is static analysis component present in Compilation stage of rust program
Compiler translates your code into step-by-step format called MIR (Mid-level Intermediate Representation).
The borrow checker looks at this MIR to track the exact liveness and initialization state of your variables line by line.
At compile time its able to find ownership BREAKAGE rules


Line of Code              State of s        State of s1           Borrow Checker Internal Action
let s = Box::new(...);    Initialized	      Uninitialized	        Memory allocated. s becomes the valid owner.
let s1 = s;               Moved (Invalid)   Initialized	          Bitwise copy to s1. State of s is changed to Moved.
println!("{}", s);        Moved (Invalid)	  Initialized	Error!    Attempted to read a variable in the "Moved" state