On-Ramp to Rust

ownership

In C, when you malloc a block of memory, the language does not record who is responsible for freeing it — that is a convention you keep in your head and your comments, and if you get it wrong you leak or double-free. Ownership is Rust's answer: it takes that informal idea of who is responsible and makes it a hard rule the compiler tracks and enforces. The promise is simple to state and surprisingly powerful: every value in a Rust program has exactly one owner at a time, and when the owner goes away, the value is cleaned up automatically.

Concretely, an owner is a variable that is bound to a value. If you write let s = String::from("hello"), then s owns that string, including the heap memory holding its characters. The rule has three parts. First, each value has one owning variable. Second, there can be only one owner at any moment — you cannot have two variables both owning the same value (that is what the move, in the next entry, is about). Third, when the owner goes out of scope — when the block it lives in ends — Rust automatically frees the value's memory by running its cleanup, called drop. You never write free; the end of the owner's scope is the free. So a String created inside a function is automatically released when the function returns, exactly when a C programmer would have had to remember to call free.

Why this matters: ownership is the single idea the rest of Rust's safety is built on. Because there is always exactly one owner, there is always exactly one place and time the memory is freed — so you cannot double-free (only the owner frees, once) and you cannot leak by simply forgetting (scope's end frees for you). It is the same discipline a careful C programmer follows with their ownership conventions, but checked by the compiler instead of trusted to a comment. The catch is that satisfying the one-owner rule changes how you pass values around, which is exactly what moves and borrows exist to handle.

fn main() { let s = String::from("hello"); // s owns the heap string greet(s); // ownership MOVES into greet } // s is gone; nothing to free here fn greet(name: String) { // name now owns it println!("hi {name}"); } // scope ends -> drop runs -> memory freed

One owner at a time; the value is freed automatically when its owner's scope ends.

Ownership is about responsibility for freeing, not about who can read a value. Many parts of the code can read a value at once through borrows; only one place owns it and is responsible for cleaning it up.

Also called
the ownership rulesingle owner所有權規則唯一擁有者