A customer wanted to know if it was okay to throw a C++ exception from a structured exception.
They explained that they didn’t want to compile their project with the /EHa switch, 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 catch statement will catch both explicitly thrown C++ exceptions (raised by the throw 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 RaiseException .
The customer explained that they didn’t want to use /EHa 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.
So they had a fiendish plan.
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 /EHa compiler option.
// This clever function is an exception filter that converts // asynchronous exceptions (structured exception handling) // to synchronous exceptions (C++ exceptions). LONG WINAPI CleverConversion( EXCEPTION_POINTERS* ExceptionInfo) { auto record = ExceptionInfo->ExceptionRecord; std::string message; ... build a message based on the exception code and other parameters ... throw std::exception(message.c_str()); } int sample_function(int* p) { try { printf("About to dereference the pointer %p
", p); return *p; } catch (std::exception& e) { Log(e.what()); } return 0; } int __cdecl main(int argc, char **argv) { SetUnhandledExceptionFilter(CleverConversion); return sample_function(nullptr); }
Neat trick, huh? All the benefits of /EHa without the overhead!
Well, except that they found that it didn’t always work.
In the example above, the catch did catch the C++ exception, but if they took out the printf , then the exception was not caught.
... continue reading