RAII & Drop Guards
Resource Acquisition Is Initialization: acquire resources in constructors, release in Drop when scope ends. Scope guards run cleanup even on panic (with unwinding).
Search across all documentation pages
Resource Acquisition Is Initialization: acquire resources in constructors, release in Drop when scope ends. Scope guards run cleanup even on panic (with unwinding).
struct TempDirGuard(tempfile::TempDir);
impl Drop for TempDirGuard {
fn drop(&mut self) { /* tempdir deletes on drop */ }
}When to reach for this: Locks, files, transactions, metric timers, restoring previous state.
struct ResetFlag<'a> { flag: &'a AtomicBool, prev: bool }
impl<'a> ResetFlag<'a> {
fn guard(flag: &'a AtomicBool, value: bool) -> Self {
let prev = flag.swap(value, Ordering::SeqCst);
ResetFlag { flag, prev }
}
}
impl Drop for ResetFlag<'_> {
fn drop(&mut self) {
self.flag.store(self.prev, Ordering::SeqCst);
}
}
fn work() {
let _g = ResetFlag::guard(&IN_PROGRESS, true);
// flag restored when _g drops
}What this demonstrates:
_g binding keeps guard alive until scope endscopeguard crate for closure-based guardsdefer pattern with scopeguard::guard((), |_| cleanup()). Mutex guards (MutexGuard) are RAII locks. tokio::spawn tasks should use RAII for in-flight counters.
finally style explicit paths too for abort builds.Drop only for sync resources._ bind - guard dropped immediately. Fix: let _guard = ... for full scope.| Alternative | Use When | Don't Use When |
|---|---|---|
try/finally manual | abort builds critical path | Normal Rust RAII |
scopeguard crate | Quick closure guard | Custom type clearer |
Explicit close() | Async shutdown | Sync file handles |
Yes with unwinding; use catch_unwind at boundary if needed.
drop(guard) before scope end.
Copy types can implement Drop with care; rare pattern.
Use nested guards or single struct owning multiple resources.
Avoid logging in Drop that may panic; keep Drop infallible.
DB transaction guard rolls back unless committed.
Record duration in Drop of timer struct.
mem::forget leaks resource intentionally; document why.
Guard fields determine auto traits; watch RefCell in guard.
Use flag atomics or counters asserted after scope.
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 16, 2026