{"id":96706,"date":"2017-07-28T07:00:00","date_gmt":"2017-07-28T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=96706"},"modified":"2019-03-13T01:14:38","modified_gmt":"2019-03-13T08:14:38","slug":"20170728-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170728-00\/?p=96706","title":{"rendered":"Can I throw a C++ exception from a structured exception?"},"content":{"rendered":"<p>A customer wanted to know if it was okay to throw a C++ exception from a structured exception. <\/p>\n<p>They explained that they didn&#8217;t want to compile their project with <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/1deeycx5.aspx\">the <code>\/EHa<\/code> switch<\/a>, which instructs the compiler to use the exception-handling model that catches both asynchronous (structured) exceptions as well as synchronous (C++) exceptions. In other words, the <code>catch<\/code> statement will catch both explicitly thrown C++ exceptions (raised by the <code>throw<\/code> statement) as well as exceptions generated by the operating system, either due to notifications from the CPU (such as an access violation or divide-by-zero) or explicit calls to <code>Raise&shy;Exception<\/code>. <\/p>\n<p>The customer explained that they didn&#8217;t want to use <code>\/EHa<\/code> because doing so significantly impairs compiler optimizations and results in larger code size. But on the other hand, they do want to catch the asynchronous (structured) exceptions. <\/p>\n<p>So they had a fiendish plan. <\/p>\n<p>Their fiendish plan is to install an unhandled exception filter which turns around and throws the C++ exception. That way, a structured exception will result in a standard C++ exception, but without the code generation penalties of the <code>\/EHa<\/code> compiler option. <\/p>\n<pre>\n\/\/ This clever function is an exception filter that converts\n\/\/ asynchronous exceptions (structured exception handling)\n\/\/ to synchronous exceptions (C++ exceptions).\n\nLONG WINAPI CleverConversion(\n    EXCEPTION_POINTERS* ExceptionInfo)\n{\n    \n    auto record = ExceptionInfo-&gt;ExceptionRecord;\n\n    std::string message;\n    ... build a message based on the exception code and\n    other parameters ...\n\n    throw std::exception(message.c_str());\n}\n\nint sample_function(int* p)\n{\n    try {\n        printf(\"About to dereference the pointer %p\\n\", p);\n        return *p;\n    } catch (std::exception&amp; e) {\n        Log(e.what());\n    }\n    return 0;\n}\n\nint __cdecl main(int argc, char **argv)\n{\n    SetUnhandledExceptionFilter(CleverConversion);\n\n    return sample_function(nullptr);\n}\n<\/pre>\n<p>Neat trick, huh? All the benefits of <code>\/EHa<\/code> without the overhead! <\/p>\n<p>Well, except that they found that it didn&#8217;t always work. <\/p>\n<p>In the example above, the <code>catch<\/code> did catch the C++ exception, but if they took out the <code>printf<\/code>, then the exception was not caught. <\/p>\n<pre>\nint sample_function(int* p)\n{\n    try {\n        return *p;\n    } catch (std::exception&amp; e) {\n        Log(e.what());          \/\/ exception not caught!\n    }\n    return 0;\n}\n<\/pre>\n<p>The customer wanted to know why the second version didn&#8217;t work. <\/p>\n<p>Actually the first version isn&#8217;t guaranteed to work either. It happens to work because the compiler must consider the possibility that the <code>printf<\/code> function might throw a C++ exception. The <code>printf<\/code> function is not marked as <code>noexcept<\/code>, so the possibility is in play. (Not that you&#8217;d expect it to be marked as such, seeing as it&#8217;s a C function, and C doesn&#8217;t have exceptions.) When the access violation is raised as a structured exception, the <code>Clever&shy;Conversion<\/code> function turns it into a C++ exception and throws it, at which point the <code>try<\/code> block catches it. But the <code>try<\/code> block is not there for the <code>Clever&shy;Conversion<\/code> exception. It&#8217;s there to catch any exceptions coming out of <code>printf<\/code>, and you just happened to be lucky that it caught your exception too. <\/p>\n<p>In the second example, there is no call to <code>printf<\/code>, so the compiler says, &#8220;Well, nothing inside this <code>try<\/code> block can throw a C++ exception, so I can optimize out the <code>try\/catch<\/code>.&#8221; You would also have observed this behavior if there were function calls inside the <code>try<\/code> block, if the function calls were all to functions that were marked <code>noexcept<\/code> or if the compiler could prove that they didn&#8217;t throw any C++ exceptions (say, because the function is inlined). <\/p>\n<p>This answers the question, but let&#8217;s try to look at the whole story. <\/p>\n<ol>\n<li>We want to use <code>\/EHa<\/code>.<\/li>\n<li>But the documentation says that <code>\/EHa<\/code>     results in less efficient code.     We want more efficient code, not less.<\/li>\n<li>Aha, we found this trick that lets us convert     asynchronous exceptions to synchronous ones.     Now we get all the benefits of <code>\/EHa<\/code>     without any of the costs!<\/li>\n<\/ol>\n<p>It looks like you found some free money on the ground, but is it really free money? <\/p>\n<p>The customer seems to think that the <code>\/EHa<\/code> option results in less efficient code simply because the compiler team is a bunch of jerks and secretly hates you. <\/p>\n<p>No, that&#8217;s not why the <code>\/EHa<\/code> option results in less efficient code. The possibility that any memory access or arithmetic operation could trigger an exception significantly impairs optimization opportunities. It means that all variables must be stable at the point memory accesses occur. <\/p>\n<p>Consider the following code fragment: <\/p>\n<pre>\nclass Reminder\n{\npublic:\n    Reminder(char* message) : m_message(message) { }\n    ~Reminder() { std::cout &lt;&lt; \"don't forget to \"\n                            &lt;&lt; m_message &lt;&lt; std::endl; }\n\n    void UpdateMessage(char* message) { m_message = message; }\n\nprivate:\n    char* m_message;\n};\n\nvoid NonThrowingFunction() noexcept;\nvoid DoSomethingElse(); \/\/ might throw\n\nvoid sample_function()\n{\n    try {\n        Reminder reminder(\"turn off the lights\");\n        if (NonThrowingFunction()) {\n            reminder.UpdateMessage(\"feed the cat\");\n        }\n        DoSomethingElse();\n    } catch (std::exception&amp; e) {\n        Log(e.what());\n    }\n}\n<\/pre>\n<p>If compiling without <code>\/EHa<\/code>, the compiler knows that the <code>Non&shy;Throwing&shy;Function<\/code> function cannot throw a C++ exception, so it can delay the store of <code>reminder.<\/code><code>m_message<\/code> to just before the call to <code>Do&shy;Something&shy;Else<\/code>. In fact, it is like to do so because it avoids a redundant store. <\/p>\n<p>The pseudo-code for this function might look like this: <\/p>\n<pre>\n    allocate 4 bytes in local frame for reminder\n\nl1:\n    call NonThrowingFunction\n    if result is zero\n        load r1 = \"turn off the lights\"\n    else\n        load r1 = \"feed the cat\"\n    endif\n    store r1 to reminder.m_message\n    call DoSomethingElse\nl2:\n    std::cout &lt;&lt; \"don't forget to \"\n              &lt;&lt; r1 &lt;&lt; std::endl;\nl3:\n\n    clean up local frame\n    return\n\nif exception occurs between l1 and l2\n    std::cout &lt;&lt; \"don't forget to \"\n              &lt;&lt; reminder.m_message &lt;&lt; std::endl;\n    fall through\n\nif exception occurs between l2 and l3\n    if exception is std::exception\n        Log(e.what())\n        goto l3\n    else\n        continue exception search\n    endif\n<\/pre>\n<p>Notice that we optimized out a redundant store by delaying the initialization of <code>reminder<\/code>, and we enregistered <code>reminder.<\/code><code>m_message<\/code> in the common code path. Delaying the initialization of <code>reminder<\/code> is not an optimization available to <code>\/EHa<\/code> because of the possibility that <code>Non&shy;Throwing&shy;Function<\/code> might raise an asynchronous exception that gets converted to a synchronous one: <\/p>\n<pre>\n    allocate 4 bytes in local frame for reminder\n\n<font COLOR=\"blue\">l0:\n    \/\/ cannot delay initialization of reminder\n    load r1 = \"turn off the lights\"\n    store r1 to reminder.m_message<\/font>\n\nl1:\n    call NonThrowingFunction\n    <font COLOR=\"blue\">if result is nonzero\n        load r1 = \"feed the cat\"\n        store r1 to reminder.m_message\n    endif<\/font>\n    call DoSomethingElse\nl2:\n    std::cout &lt;&lt; \"don't forget to \"\n              &lt;&lt; r1 &lt;&lt; std::endl;\nl3:\n\n    clean up local frame\n    return\n\nif exception occurs between l1 and l2\n    std::cout &lt;&lt; \"don't forget to \"\n              &lt;&lt; reminder.m_message &lt;&lt; std::endl;\n    fall through\n\n<font COLOR=\"blue\">\/\/ and there is a new exception region<\/font>\nif exception occurs between <font COLOR=\"blue\">l0 and l1<\/font>, or between l2 and l3\n    if exception is std::exception\n        Log(e.what())\n        goto l3\n    else\n        continue exception search\n    endif\n<\/pre>\n<p>The extra code is necessary in order to ensure that the <code>reminder<\/code> variable is in a stable state before calling <code>Non&shy;Throwing&shy;Function<\/code>. In general, if you turn on <code>\/EHa<\/code>, the compiler must ensure that every object which is accessed outside the <code>try<\/code> block (either explicitly in code or implicitly via an unwind destructor) is stable in memory before performing any operation that could result in an asynchronous exception, such as accessing memory. <\/p>\n<p>This requirement that variables be stable in memory comes at a high cost, because it not only forces redundant stores to memory, but it also prohibits various types of optimizations based on out-of-order operations. <\/p>\n<p>The <code>Clever&shy;Conversion<\/code> is basically a manual replication of what <code>\/EHa<\/code> does, but lying to the compiler and saying, &#8220;Um, yeah, don&#8217;t worry about asynchronous exceptions.&#8221; <\/p>\n<p>Observe what happens if an asynchronous exception occurs inside <code>Non&shy;Throwing&shy;Function<\/code> even though you compiled without the <code>\/EHa<\/code> flag: <\/p>\n<p>We destruct the <code>reminder<\/code> object, which means printing the <code>m_message<\/code> to <code>std::<\/code><code>cout<\/code>. But the non-<code>\/EHa<\/code> version did not ensure that <code>reminder.<\/code><code>m_message<\/code> was stable. Indeed, if an exception occurs inside <code>Non&shy;Throwing&shy;Function<\/code>, we will try to print <code>reminder.<\/code><code>m_message<\/code> anyway, even though it is an uninitialized variable. <\/p>\n<p>Printing an uninitialized variable is probably not what the program intended. <\/p>\n<p>So a more complete answer to the scenario is &#8220;Yes, it is technically possible to throw a C++ exception from a structured exception handler, but doing so requires that the program be compiled with <code>\/EHa<\/code> in order to avoid undefined behavior.&#8221; <\/p>\n<p>And given that avoiding the <code>\/EHa<\/code> flag was the whole purpose of the exercise, the answer to the specific scenario is, &#8220;No, this doesn&#8217;t work. Your program will behave in undefined ways.&#8221; <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Technically okay, but it&#8217;s unusual and doesn&#8217;t solve your problem.<\/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-96706","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Technically okay, but it&#8217;s unusual and doesn&#8217;t solve your problem.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96706","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=96706"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96706\/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=96706"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=96706"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=96706"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}