C.W.K.
Stream
Lesson 05 of 05 · published

Drop and RAII

~12 min · ownership, drop, raii, scope

Level 0Rust Curious
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

You've seen the phrase 'freed when the owner goes out of scope' a few times now. This lesson makes that mechanism explicit — it's called RAII, and it's one of the quietest, most powerful ideas in the language.

Scope ends, value drops

When a variable goes out of scope, Rust automatically calls drop on it, releasing whatever it owns. For a String, that frees the heap buffer. You never write free(); the closing brace is the free. It happens deterministically, at a compile-time-known point — not 'eventually,' the way a garbage collector works.

RAII — resources tied to scope

This generalizes far past memory. A file handle, a network socket, a mutex lock — all can tie their cleanup to drop. Open a file, and when the owning variable leaves scope, the file closes. Acquire a lock, and when the guard drops, the lock releases. The resource's lifetime is the variable's scope. That's RAII: Resource Acquisition Is Initialization.

The closing brace is the cleanup. Memory, files, locks, sockets — if a type owns a resource, its Drop implementation releases it exactly when the owner's scope ends. No leaks, no 'did I remember to close that?', no GC pause.

Custom Drop

You can implement Drop for your own types to run code at the end of scope — flush a buffer, log a shutdown, release a handle. You rarely call drop by hand (the compiler does it); you just define what cleanup means, and it runs automatically.

Why this matters for everything after

Ownership decided who frees. Drop decides when: precisely at the end of the owner's scope. Hold those two together and you understand the spine of Rust — every later topic (borrowing, lifetimes, smart pointers) is a refinement of 'who owns this, and when does it drop?'

Code

Drop runs at the end of scope·rust
struct Guard { label: String }

impl Drop for Guard {
    fn drop(&mut self) {
        // runs automatically when a Guard leaves scope
        println!("releasing {}", self.label);
    }
}

fn main() {
    let _outer = Guard { label: String::from("outer") };
    {
        let _inner = Guard { label: String::from("inner") };
        println!("inner scope");
    } // _inner drops HERE -> prints "releasing inner"
    println!("outer scope");
} // _outer drops HERE -> prints "releasing outer" (reverse order)

External links

Exercise

Implement Drop for a struct that prints a message. Create two of them in nested scopes and predict the order the messages print before you run it. Were you right about the reverse ordering?
Hint
Last created, first dropped. The inner-scope value drops at its closing brace; the outer one drops at the end of main.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue
💛 by Ttoriwarm

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.