Error Handling & Robustness

RAII and scope-bound cleanup

/ RAII: "R-A-I-I" (spelled out) /

Imagine a hotel keycard that automatically locks your room the instant you leave - you cannot forget to lock up, because leaving is locking. RAII (resource acquisition is initialization, pronounced by spelling the letters out) is that idea applied to resources in code: tie a resource's lifetime to a variable's scope, so that when the variable goes out of scope - by any exit, including an error - the resource is automatically released. You acquire in a constructor; you release in a destructor; the language runs the destructor for you when the variable's scope ends.

Here is the mechanism, the C++/Rust answer to the cleanup problem. In C++, a class owns a resource: its constructor acquires it (opens the file, allocates the memory, takes the lock) and its destructor releases it (closes, frees, unlocks). When you create such an object as a local variable, the compiler guarantees the destructor runs the moment control leaves the scope - whether by reaching the closing brace, by return, or by an exception unwinding through it. So cleanup is not something you remember to write at each exit; it is attached to the object and happens automatically and exactly once. Rust takes the same idea and bakes it into the language as ownership and the Drop trait: when a value's owner goes out of scope, its drop code runs. The std::lock_guard in C++ and the MutexGuard in Rust are textbook examples - the lock is released when the guard variable's scope ends, even if an error bails out in the middle.

Why it matters: RAII largely dissolves the cleanup problem that goto-cleanup laboriously works around. There is no separate cleanup label to keep in sync with acquisitions, no risk of a new early return forgetting to release, because release is the destructor's job, not yours. This is one of the strongest arguments for C++ and Rust over plain C in resource-heavy systems code. The honest caveats: RAII needs language support (destructors / Drop) that C simply does not have, which is why C falls back on goto-cleanup; and RAII does not magically prevent every leak - cycles of reference-counted pointers can still leak, and you must still design ownership correctly. It removes a whole class of mistakes, not all of them.

In C++: { std::lock_guard<std::mutex> g(m); do_work(); } - the lock is taken when g is created and released the instant the block ends, even if do_work() throws an exception. The C equivalent needs an explicit pthread_mutex_unlock() on every single exit path - the very thing goto-cleanup exists to manage.

The guard's destructor unlocks automatically on every exit; the C version must do it by hand.

RAII needs destructors or Drop - features C does not have, which is exactly why C uses goto-cleanup instead. And it is not a leak-proof guarantee: reference cycles can still leak, and bad ownership design still bites. It removes a class of mistakes, not all of them.

Also called
resource acquisition is initializationscope-bound resource management資源取得即初始化