TL;DR

C++ lacks a dedicated finally clause; instead, developers rely on destructors to run cleanup when control leaves a scope. That approach works, but if a destructor throws while another exception is active the program will terminate, unlike the overwrite behavior seen in many other languages.

What happened

Many modern languages with exceptions provide a finally clause to guarantee execution of cleanup code when control leaves a block (examples include Java, C#, Python and JavaScript). C++ does not include a language-level finally construct. Instead, C++ programmers use destructors to achieve the same effect: an object whose destructor runs on scope exit can invoke cleanup code. A common utility is the Windows Implementation Library’s wil::scope_exit, which stores a lambda in an object whose destructor executes that lambda when the object goes out of scope. The languages differ in how they handle exceptions thrown from cleanup code. If no exception is active when the cleanup runs, any exception from the cleanup propagates normally. If an exception is already propagating and the cleanup throws as well, Java, C#, JavaScript and Python discard the original exception in favor of the new one (with Python 3.2+ preserving the original as context), while C++ will terminate the program if a destructor throws during stack unwinding. wil::scope_exit documents this termination behavior and offers a variant that logs and ignores destructor-thrown exceptions.

Why it matters

  • C++ resource cleanup idioms rely on destructors; their exception behavior differs from finally clauses in other languages.
  • Throwing exceptions from cleanup code during stack unwinding can terminate a C++ program, so cleanup lambdas must avoid propagating exceptions.
  • Libraries such as wil provide scope-guard helpers but developers must choose variants deliberately (e.g., logging-and-ignoring vs. allowing exceptions).
  • Using compiler-specific structured exception keywords for C (e.g., __try/__finally) is supported by MSVC but is not intended for C++ and can interact poorly with C++ exceptions.

Key facts

  • Java, C#, Python and JavaScript include a finally clause that runs when control leaves a try block.
  • C++ does not have a built-in finally clause; destructors serve the role of running code on scope exit.
  • wil::scope_exit places a user-provided lambda inside an object whose destructor executes the lambda on scope exit.
  • If no exception is active when cleanup runs, any exception thrown by cleanup propagates from the original try block in all these languages.
  • If an exception is already propagating and the cleanup throws too, Java/C#/JavaScript and older Python versions replace the original exception with the new one.
  • Python 3.2 and later preserve the original exception as the context of the new exception, but the new exception is still the one thrown.
  • In C++, if a destructor throws while another exception is active (during stack unwinding), the runtime will terminate the program.
  • wil::scope_exit documents that it will terminate the process if the lambda throws; wil::scope_exit_log logs and ignores such exceptions instead.
  • MSVC supports __try and __finally for structured exception handling in C, but those constructs are not recommended for use in C++.

What to watch next

  • Developers using scope-guard utilities must ensure cleanup lambdas do not allow exceptions to escape during stack unwinding.
  • Consider using wil::scope_exit_log if you need the cleanup to ignore or log exceptions rather than risk termination.
  • not confirmed in the source

Quick glossary

  • Destructor: A special class function in C++ that runs automatically when an object goes out of scope or is destroyed; often used for cleanup.
  • finally clause: A language construct in many exception-handling systems that guarantees execution of a code block when control leaves a try block.
  • Stack unwinding: The process of unwinding the call stack and running destructors or cleanup code as exceptions propagate.
  • Scope guard: A programming pattern or utility that runs specified cleanup code when execution leaves a scope, typically via RAII or destructors.

Reader FAQ

Does C++ have a finally clause?
Not in the language; C++ uses destructors (RAII) to run cleanup when a scope is exited.

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

Do other languages handle destructor/finally exceptions the same way?
No. Java, C#, JavaScript and Python generally replace the original exception with the one thrown in finally; Python 3.2+ preserves the original as context but still throws the new exception.

Can I use MSVC __try/__finally in C++?
MSVC provides __try and __finally for structured exception handling in C, but their use in C++ is discouraged because they interact with C++ exceptions in confusing ways.

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 *