Safeguard
Developer Tools•

Rust ownership rules and the memory bugs they prevent

Three ownership rules let the Rust compiler stop double free and use of moved values at compile time. Here are the rules, with a short worked example.

Safeguard Security Team
4 min read

Rust prevents double free and use of released memory with three ownership rules that the compiler checks: each value has one owner, there is only one owner at a time, and the value is dropped when the owner goes out of scope. Breaking a rule is a compile error, not a runtime crash.

The rules

From the Rust book:

  1. Each value in Rust has an owner.
  2. There can only be one owner at a time.
  3. When the owner goes out of scope, the value will be dropped.

Dropping means Rust calls the drop function at the closing brace, which returns heap memory to the allocator. You never write a free call.

How double free is blocked

The book's example assigns one string variable to another. A plain copy of the pointer, length and capacity would leave two variables pointing at the same heap memory, and both would try to free it when they leave scope. That is a double free.

Rust avoids it with a move. After the assignment the first variable is no longer valid, and only the second frees the memory.

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

    println!("{s1}, world!"); // compile error: borrow of moved value
}

The compiler rejects the use of the moved value. In C the same pattern compiles and corrupts the heap at run time.

Copy versus clone

Simple types such as integers, booleans, characters and floats implement Copy, so the original stays valid. If you really want two independent heap copies, you call clone, which is explicit. Rust never makes automatic deep copies.

Borrowing in one paragraph

Moving is not the only way to use a value. You can lend it with a reference, and the compiler tracks how long the loan lasts. The Rust Reference describes the aliasing rules in terms of undefined behavior: a shared reference must not be mutated while it is live, and a mutable reference must not be accessed through other pointers while live. In safe code the compiler enforces these rules for you.

This is why use after free is so hard to write in safe Rust. A reference cannot outlive the value it points to, and a value cannot be freed while a reference to it is still in use. In C the programmer holds those facts in their head, and review has to catch the mistake.

Why this matters for migration

If your C code base has recurring double free and use after free bugs, the ownership model is the part of Rust that addresses them most directly. Spatial bugs are addressed by bounds checks on indexing, which safe Rust performs as well. Both are properties of safe Rust, not of the team using it.

What this does and does not give you

Safe Rust code gets these checks from the compiler for these rules. They cover a large share of temporal bugs. They do not remove:

  • Logic errors, such as a wrong access control decision.
  • Bugs in unsafe blocks, where the programmer upholds the rules, as the Rust Reference states.
  • Bugs in C libraries called through FFI.

Reading the compiler errors

New Rust users often fight the borrow checker. A useful habit is to ask who owns the value at each line, and to pass references for temporary use. When the compiler complains, it is usually pointing at a real aliasing or lifetime mistake that would be a latent bug in C.

Quick check

Does Rust use a garbage collector to free memory?

No. Values are dropped deterministically when their owner goes out of scope, as described in the Rust book.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.