{"id":3236,"date":"2011-01-25T11:51:00","date_gmt":"2011-01-25T11:51:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/subterranean-il-compiling-c-exception-handlers\/"},"modified":"2021-04-29T15:30:54","modified_gmt":"2021-04-29T15:30:54","slug":"subterranean-il-compiling-c-exception-handlers","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/subterranean-il-compiling-c-exception-handlers\/","title":{"rendered":"Subterranean IL: Compiling C# exception handlers"},"content":{"rendered":"<p>An exception handler in C# combines the IL <code>catch<\/code> and <code>finally<\/code> exception handling clauses into a single <code>try<\/code> statement: <\/p>\n<pre>try {\n    Console.WriteLine(\"Try block\")\n    \/\/ ...\n}\ncatch (IOException) {\n    Console.WriteLine(\"IOException catch\")\n    \/\/ ...\n}\ncatch (Exception e) {\n    Console.WriteLine(\"Exception catch\")\n    \/\/ ...\n}\nfinally {\n    Console.WriteLine(\"Finally block\")\n    \/\/ ...\n}<\/pre>\n<p>How does this get compiled into IL?<\/p>\n<p><b>Initial implementation<\/b><\/p>\n<p> If you remember from <a href=\"https:\/\/www.simple-talk.com\/community\/blogs\/simonc\/archive\/2011\/01\/13\/98744.aspx\">my earlier post<\/a>, <code>finally<\/code> clauses must be specified with their own <code>.try<\/code> clause. So, for the initial implementation, we take the try\/catch\/finally, and simply split it up into two <code>.try<\/code> clauses (I have to use label syntax for this): <\/p>\n<pre>StartTry:\n    ldstr \"Try block\"\n    call void [mscorlib]System.Console::WriteLine(string)\n    \/\/ ...\n    leave.s End\nEndTry:\n\nStartIOECatch:\n    ldstr \"IOException catch\"\n    call void [mscorlib]System.Console::WriteLine(string)\n    \/\/ ...\n    leave.s End\nEndIOECatch:\n\nStartECatch:\n    ldstr \"Exception catch\"\n    call void [mscorlib]System.Console::WriteLine(string)\n    \/\/ ...\n    leave.s End\nEndECatch:\n\nStartFinally:\n    ldstr \"Finally block\"\n    call void [mscorlib]System.Console::WriteLine(string)\n    \/\/ ...\n    endfinally\nEndFinally:\n  \nEnd:\n   \/\/ ...\n   \n.try StartTry to EndTry\n    catch [mscorlib]System.IO.IOException\n        handler StartIOECatch to EndIOECatch\n    catch [mscorlib]System.Exception\n        handler StartECatch to EndECatch\n.try StartTry to EndTry\n    finally handler StartFinally to EndFinally<\/pre>\n<\/p>\n<p>However, the resulting program isn&#8217;t verifiable, and doesn&#8217;t run: <\/p>\n<pre>[IL]: Error: Shared try has finally or fault handler.<\/pre>\n<p><b>Nested try blocks<\/b><\/p>\n<p>What&#8217;s with the verification error? Well, it&#8217;s a condition of IL verification that all exception handling regions (<code>try<\/code>, <code>catch<\/code>, <code>filter<\/code>, <code>finally<\/code>, <code>fault<\/code>) of a single <code>.try<\/code> clause have to be completely contained within any outer exception region, and they can&#8217;t overlap with any other exception handling clause. In other words, IL exception handling clauses <em>must<\/em> to be representable in the scoped syntax, and in this example, we&#8217;re overlapping <code>catch<\/code> and <code>finally<\/code> clauses.<\/p>\n<p>Not only is this example not verifiable, it isn&#8217;t semantically correct. The <code>finally<\/code> handler is specified round the <code>.try<\/code>. What happens if you were able to run this code, and an exception was thrown? <\/p>\n<ol>\n<li>Program execution enters top of <code>try<\/code> block, and exception is thrown within it<\/li>\n<li>CLR searches for an exception handler, finds <code>catch<\/code><\/li>\n<li>Because control flow is leaving <code>.try<\/code>, <code>finally<\/code> block is run<\/li>\n<li>The <code>catch<\/code> block is run<\/li>\n<li><code>leave.s End<\/code> inside the catch handler branches to <code>End<\/code> label.<\/li>\n<\/ol>\n<p> We&#8217;re actually running the <code>finally<\/code> before the <code>catch<\/code>!<\/p>\n<p><b>What we do about it<\/b><\/p>\n<p>What we actually need to do is put the <code>catch<\/code> clauses <em>inside<\/em> the <code>finally<\/code> clause, as this will ensure the <code>finally<\/code> gets executed at the correct time (this time using scoped syntax): <\/p>\n<pre>.try {\n    .try {        \n        ldstr \"Try block\"\n        call void [mscorlib]System.Console::WriteLine(string)\n        \/\/ ...\n        leave.s End\n    }\n    catch [mscorlib]System.IO.IOException {\n        ldstr \"IOException catch\"\n        call void [mscorlib]System.Console::WriteLine(string)\n        \/\/ ...\n        leave.s End\n    }\n    catch [mscorlib]System.Exception {\n        ldstr \"Exception catch\"\n        call void [mscorlib]System.Console::WriteLine(string)\n        \/\/ ...\n        leave.s End\n    }\n}\nfinally {\n    ldstr \"Finally block\"\n    call void [mscorlib]System.Console::WriteLine(string)\n    \/\/ ...\n    endfinally\n}\n\nEnd:\n    ret<\/pre>\n<p><b>Returning from methods<\/b><\/p>\n<p>There is a further semantic mismatch that the C# compiler has to deal with; in C#, you are allowed to <code>return<\/code> from within an exception handling block: <\/p>\n<pre>public int HandleMethod() {\n    try {\n        \/\/ ...\n        return 0;\n    }\n    catch (Exception) {\n        \/\/ ...\n        return -1;\n    }\n}<\/pre>\n<\/p>\n<p>However, you can&#8217;t <code>ret<\/code> inside an exception handling block in IL. So the C# compiler does a <code>leave.s<\/code> to a <code>ret<\/code> outside the exception handling area, loading\/storing any return value to a local variable along the way (as <code>leave.s<\/code> clears the stack): <\/p>\n<pre>.method public instance int32 HandleMethod() {\n    .locals init ( int32 retVal )\n    \n    .try {\n        \/\/ ...\n        ldc.i4.0\n        stloc.0\n        leave.s End\n    }\n    catch [mscorlib]System.Exception {\n        \/\/ ...\n        ldc.i4.m1\n        stloc.0\n        leave.s End\n    }\n    \n  End:\n    ldloc.0\n    ret\n}<\/pre>\n<p><b>Conclusion<\/b><\/p>\n<p>As you can see, the C# compiler has quite a few hoops to jump through to translate C# code into semantically-correct IL, and hides the numerous conditions on IL exception handling blocks from the C# programmer.<\/p>\n<p><a href=\"https:\/\/www.simple-talk.com\/community\/blogs\/simonc\/archive\/2011\/02\/09\/99250.aspx\">Next time<\/a>: onto <code>fault<\/code> handlers.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>An exception handler in C# combines the IL catch and finally exception handling clauses into a single try statement: try { Console.WriteLine(&#8220;Try block&#8221;) \/\/ &#8230; } catch (IOException) { Console.WriteLine(&#8220;IOException catch&#8221;) \/\/ &#8230; } catch (Exception e) { Console.WriteLine(&#8220;Exception catch&#8221;) \/\/ &#8230; } finally { Console.WriteLine(&#8220;Finally block&#8221;) \/\/ &#8230; } How does this get compiled&#8230;&hellip;<\/p>\n","protected":false},"author":186659,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538,2],"tags":[],"coauthors":[],"class_list":["post-3236","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3236","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/186659"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=3236"}],"version-history":[{"count":3,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3236\/revisions"}],"predecessor-version":[{"id":75606,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3236\/revisions\/75606"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=3236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=3236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=3236"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=3236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}