{"id":111890,"date":"2025-12-22T07:00:00","date_gmt":"2025-12-22T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111890"},"modified":"2025-12-24T11:26:30","modified_gmt":"2025-12-24T19:26:30","slug":"all-the-other-cool-languages-have-try-finally-c-says-we-have-try-finally-at-home","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20251222-00\/?p=111890","title":{"rendered":"All the other cool languages have <CODE>try<\/CODE>&#8230;<CODE>finally<\/CODE>. C++ says &#8220;We have <CODE>try<\/CODE>&#8230;<CODE>finally<\/CODE> at home.&#8221;"},"content":{"rendered":"<p>Many languages\u00b9 that have exceptions also have a <code>finally<\/code> clause, so you can write<\/p>\n<pre>try {\r\n    \u27e6 stuff \u27e7\r\n} finally {\r\n    always();\r\n}\r\n<\/pre>\n<p>A quick checks shows that this control structure exists in Java, C#, Python, JavaScript, but not C++.<\/p>\n<p>C++ says, &#8220;We have <code>try<\/code>&#8230;finally at home.&#8221;<\/p>\n<p>In C++, the way to get a block of code to execute when control leaves a block is to put it in a destructor, because destructors run when control leaves a block. This is the trick used by the Windows Implementation Library&#8217;s <a href=\"https:\/\/github.com\/microsoft\/wil\/wiki\/RAII-resource-wrappers#wilscope_exit\"> wil::<wbr \/>scope_exit<\/a> function: The lambda you provide is placed inside a custom object whose destructor runs the lambda.<\/p>\n<pre>auto ensure_cleanup = wil::scope_exit([&amp;] { always(); });\r\n\r\n\u27e6 stuff \u27e7\r\n<\/pre>\n<p>Although the principle is the same, there are some quirks in how each language treats the case where the <code>finally<\/code> or destructor itself throws an exception.<\/p>\n<p>If control leaves the guarded block without an exception, then any uncaught exception that occurs in the <code>finally<\/code> block or the destructor is thrown from the <code>try<\/code> block. All the languages seem to agree on this.<\/p>\n<p>If control leaves the guarded block with an exception, and the <code>finally<\/code> block or destructor <i>also<\/i> throws an exception, then the behavior varies by language.<\/p>\n<ul>\n<li>In Java, Python, JavaScript, and C# an exception thrown from a <code>finally<\/code> block overwrites the original exception, and the original exception is lost. <b>Update<\/b>: Adam Rosenfield points out that Python 3.2 now saves the original exception as the context of the new exception, but it is still the new exception that is thrown.<\/li>\n<li>In C++, an exception thrown from a destructor triggers automatic program termination if the destructor is running due to an exception.\u00b2<\/li>\n<\/ul>\n<p>So C++ gives you the ability to run code when control leaves a scope, but your code had better not allow an exception to escape if you know what&#8217;s good for you.<\/p>\n<p>\u00b9 The Microsoft compiler also supports the <code>__try<\/code> and <code>__finally<\/code> keywords for structured exception handling. These are, however, intended for C code. Don&#8217;t use them in C++ code because <a title=\"Can I throw a C++ exception from a structured exception?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170728-00\/?p=96706\"> they interact with C++ exceptions in sometimes-confusing ways<\/a>.<\/p>\n<p>\u00b2 This is why <code>wil::<wbr \/>scope_exit<\/code> documents that it will terminate the process if the lambda throws an exception. There is an alternate function <code>wil::<wbr \/>scope_<wbr \/>exit_<wbr \/>log<\/code> that logs and then ignores exceptions that are thrown from the lambda. There is no variation that gives you Java-like behavior.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The destructor serves as the &#8220;finally&#8221;.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-111890","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The destructor serves as the &#8220;finally&#8221;.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111890","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=111890"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111890\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=111890"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111890"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111890"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}