DEV Community

The Practical Developer
The Practical Developer

Posted on Originally published at practicaldevblog.blogspot.com

Rust Explained: Memory Safety Without a Garbage Collector

Introduction

Rust promises something that sounds impossible: the speed of C and C++, without their most famous class of bugs — crashes and security holes caused by bad memory handling — and without a garbage collector pausing your program to clean up.

The trick is not magic. It is a set of rules, checked by the compiler before your program ever runs, called ownership.

Ownership: every value has one owner

In Rust, every value has exactly one owner — the variable that holds it. When the owner goes out of scope, the value is cleaned up automatically. Move the value to another variable, and the first one can no longer use it.

fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // s1 is moved, not copied
    // println!("{}", s1); // Error: s1 no longer owns the value
    println!("{}", s2); // Works
}
Enter fullscreen mode Exit fullscreen mode

This looks annoying at first, and it is, briefly. But it eliminates an entire category of bugs: no two parts of a program can accidentally free the same memory, and nothing is used after it has been freed, because the compiler refuses to compile such code.

Borrowing: use it without owning it

Most of the time you do not want to give a value away — you just want to look at it. Borrowing lets a function use a value by reference, without taking ownership.

fn calculate_length(s: &String) -> usize {
    s.len()
}
fn main() {
    let s = String::from("hello");
    let len = calculate_length(&s);
    println!("{} is {} long", s, len); // s still works here
}
Enter fullscreen mode Exit fullscreen mode

The & means "borrow this". The borrow checker enforces one rule: you can have either any number of read-only borrows, or exactly one writable borrow — never both at once. That single rule prevents data races, the bugs where two threads change the same data simultaneously.

The borrow checker is a teacher, not an enemy

Every Rust beginner fights the borrow checker. The secret experienced Rust developers share: the errors it reports are almost always real bugs that other languages would let through, to surface later as crashes in production. Fixing them at compile time is the whole point.

A good way to learn: write the code the way you would in another language, read the compiler's error carefully — Rust's error messages are famously helpful, often suggesting the exact fix — and adjust.

Where Rust shines

Rust is most at home where speed and reliability both matter: systems software, command-line tools, web servers, game engines, and WebAssembly (running compiled code in the browser). If a program must be fast and must never crash from memory errors, Rust is the strongest modern choice.

Takeaway

One owner per value, borrowing instead of copying when you only need to look, and a compiler that refuses unsafe code before it runs. Learn those three ideas, and Rust's reputation for difficulty starts to look like a reputation for thoroughness.

Originally published at https://practicaldevblog.blogspot.com/2026/10/rust-explained-memory-safety-without.html

Top comments (0)