TL;DR
Many modern languages provide a finally clause for guaranteed cleanup; C++ accomplishes the same goal using destructors and RAII-style scope guards. That approach works, but if a destructor throws while another exception is active, C++ will terminate the process rather than emulate other languages' finally semantics.
What happened
Languages such as Java, C#, Python and JavaScript provide a try…finally construct that runs a cleanup block when control leaves a guarded section. C++ does not offer a finally keyword; instead, developers rely on destructors and RAII to run code on scope exit. Libraries like the Windows Implementation Library (wil) provide helpers such as wil::scope_exit that wrap a lambda in an object whose destructor invokes the cleanup lambda when the object goes out of scope. While the mechanical effect—running code on scope exit—is equivalent, languages differ in how they handle exceptions thrown from the cleanup code. If no exception is active when the cleanup runs, exceptions from finally/destructor propagate normally. But if the guarded block is already unwinding for an exception and the cleanup also throws, many languages replace the original exception with the new one; in C++, throwing from a destructor during stack unwinding causes immediate program termination. wil::scope_exit documents this behavior and offers wil::scope_exit_log as an alternative that logs and swallows such exceptions.
Why it matters
- C++ programmers use destructors and scope guards instead of a finally keyword to ensure cleanup on scope exit.
- Cleanup code must avoid letting exceptions escape during stack unwinding, because a thrown exception in a destructor will terminate the program.
- Porting code from languages with finally to C++ requires careful handling of exceptions in cleanup to avoid losing original errors or causing termination.
- wil::scope_exit is a common helper for scope-based cleanup; wil::scope_exit_log is offered when callers prefer logging and ignoring exceptions from cleanup.
Key facts
- Java, C#, Python and JavaScript include a finally clause for code that must run when control leaves a try block.
- C++ achieves the same effect by placing cleanup logic in destructors; destructors run when an object goes out of scope.
- wil::scope_exit places a provided lambda inside an object whose destructor executes that lambda on scope exit.
- If no exception is active when finally/destructor runs, any uncaught exception from the cleanup is propagated.
- If an exception is already active and the finally block/destructor throws, Java/C#/JavaScript/Python overwrite the original exception with the new one.
- Python 3.2 records the original exception as the context of the new exception, but still throws the new exception.
- In C++, throwing an exception from a destructor during stack unwinding triggers process termination (std::terminate).
- The Microsoft compiler also supports __try/__finally for structured exception handling in C, but these are not intended for use in C++ due to interaction with C++ exceptions.
- wil::scope_exit documents that it will terminate the process if the lambda throws; wil::scope_exit_log logs and ignores such exceptions instead.
What to watch next
- Avoid allowing cleanup lambdas or destructors to throw when they may run while an exception is already active; otherwise the program can terminate.
- When converting code that uses finally from other languages to C++, review cleanup paths and consider using safe scope-guard helpers like wil::scope_exit_log if you need to ignore or log cleanup errors.
- Do not rely on Microsoft __try/__finally in C++ code; the source advises these are intended for C and can interact confusingly with C++ exceptions.
Quick glossary
- Destructor: A special C++ member function that runs when an object goes out of scope or is deleted, used to release resources and perform cleanup.
- finally clause: A language construct present in several languages that guarantees execution of a block of code when control leaves a try block, regardless of whether an exception occurred.
- RAII (Resource Acquisition Is Initialization): A C++ programming idiom where resources are tied to object lifetime so that acquiring a resource happens at construction and releasing it happens in the destructor.
- Scope guard / scope_exit: A helper object pattern that runs a specified callable when it goes out of scope, commonly used to ensure cleanup in C++.
- Stack unwinding: The process of destroying automatic objects as the runtime backs out of nested function calls while propagating an exception.
Reader FAQ
Does C++ have a finally keyword?
No; C++ does not include a finally language construct. The same effect is achieved by running cleanup in destructors (RAII).
What happens if a destructor throws while an exception is active?
C++ will call std::terminate (process termination) if a destructor throws during stack unwinding.
Can I use __try/__finally in C++ with the Microsoft compiler?
The Microsoft compiler supports __try/__finally for C, but the source advises not to use them in C++ because they interact with C++ exceptions in sometimes-confusing ways.
Does wil::scope_exit swallow exceptions from the cleanup lambda?
No; wil::scope_exit documents that it will terminate the process if the lambda throws. There is wil::scope_exit_log which logs and ignores exceptions.
Do other languages preserve the original exception when finally throws a new one?
In Java, C#, JavaScript and older Python versions the new exception replaces the original. Python 3.2 and later records the original exception as context while still raising the new exception.

Many languages¹ that have exceptions also have a finally clause, so you can write try { ⟦ stuff ⟧ } finally { always(); } A quick checks shows that this…
Sources
Related posts
- How Much Melatonin Should You Take? Guidance, Risks, and Alternatives
- Growing Up in 404: Life Inside China’s Secret Nuclear City in the Gobi
- Daily Bottled-Water Drinkers Swallow About 90,000 Extra Microplastic Particles