TL;DR

Many modern languages offer a finally clause to run cleanup when control leaves a block; C++ provides the same effect via destructors and RAII. That approach works but has different exception semantics — notably, a destructor that throws during stack unwinding will terminate the program.

What happened

Raymond Chen's Dev Blog post contrasts the explicit try…finally construct found in languages such as Java, C#, Python and JavaScript with the C++ approach. C++ does not include a dedicated finally keyword; instead, developers rely on destructors and RAII to run code when a scope is exited. Libraries like the Windows Implementation Library (wil) expose helpers such as wil::scope_exit that store a lambda in an object whose destructor invokes the cleanup action when the object goes out of scope. The post then highlights divergent behaviors when cleanup code itself raises an exception: if no prior exception exists, any exception from finally/destructor is propagated; but if an exception is already propagating, languages differ — many replace the original exception with the new one while C++ will abort if a destructor throws during stack unwinding. Microsoft also provides __try/__finally for C, but the blog cautions against using that in C++.

Why it matters

  • C++ developers achieve deterministic cleanup without a finally keyword by leveraging destructors and RAII.
  • Exception-handling semantics differ across languages; relying on destructor-based cleanup requires care to avoid terminating the process during stack unwinding.
  • Library choices (e.g., wil::scope_exit vs wil::scope_exit_log) affect how cleanup exceptions are handled in C++ code.
  • Mixing structured-exception keywords intended for C with C++ exceptions can produce confusing interactions; the Microsoft __try/__finally is intended for C only.

Key facts

  • Languages with a finally clause mentioned: Java, C#, Python, JavaScript.
  • C++ has no built-in try…finally construct; destructors run when control leaves a scope and are used for cleanup instead.
  • wil::scope_exit places the provided lambda inside an object whose destructor runs the lambda at scope exit.
  • If control leaves the guarded block without an existing exception, an exception raised in finally or a destructor is propagated normally.
  • If an exception is already propagating and finally/destructor throws, Java, Python, JavaScript and C# overwrite the original exception with the new one.
  • Python 3.2 introduced preserving the original exception as the context of the new exception, though the new exception is still the one raised.
  • In C++, if a destructor throws while another exception is already propagating (during stack unwinding), the program is terminated.
  • wil::scope_exit documents that it will terminate the process if the lambda throws; wil::scope_exit_log is an alternative that logs and ignores exceptions thrown from the lambda.
  • The Microsoft compiler supports __try and __finally for structured exception handling in C, but those constructs are not recommended for use in C++.

What to watch next

  • Make sure cleanup code run from destructors does not allow exceptions to escape, especially during stack unwinding.
  • When using wil::scope_exit, note that a thrown exception from the lambda will terminate the process; consider wil::scope_exit_log if you want to log-and-ignore.
  • not confirmed in the source

Quick glossary

  • RAII: Resource Acquisition Is Initialization — a C++ idiom where resource lifetime is tied to object lifetime; destructors release resources when objects go out of scope.
  • Destructor: A special member function in C++ that runs when an object is destroyed, typically used to free resources or run cleanup code.
  • finally clause: A language construct in some languages that guarantees execution of a block of code when control leaves a try block, regardless of whether an exception occurred.
  • Stack unwinding: The process of unwinding the call stack during exception propagation, calling destructors for automatic objects as execution moves up the stack.

Reader FAQ

Does C++ have a finally keyword?
No — C++ does not provide a finally clause; developers use destructors and RAII to run cleanup at scope exit.

What happens if a destructor throws while another exception is propagating?
In C++, that situation causes automatic program termination (process abort).

Can I use __try/__finally in MSVC to get finally behavior in C++?
The Microsoft compiler supports __try/__finally for structured exception handling in C, but the blog advises not to use those constructs in C++ because they interact with C++ exceptions in confusing ways.

Does wil::scope_exit mimic Java-style finally behavior?
No — wil::scope_exit will terminate the process if the cleanup lambda throws; wil::scope_exit_log exists to log and ignore such exceptions, and there is no variant that gives Java-like exception-overwrite semantics.

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

By

Leave a Reply

Your email address will not be published. Required fields are marked *