What should I know about Structured Exceptions (SEH) in C++?

What important points about Structured Exceptions should every C++ developer know?


Solution 1:

They are the Win32 equivalent to Unix signals, and let you catch CPU exceptions such as access violation, illegal instruction, divide by zero.

With the right compiler options (/EHa for Visual C++), C++ exceptions use the same mechanism as stack unwinding works properly for both C++ (user) exceptions and SEH (OS) exceptions.

Unlike C++ exceptions, SEH are not typed but all share the same data structure which has an exception code (the cause) and additional information on what code faulted and what the CPU registers held at the time of the fault. See GetExceptionCode and GetExceptionInformation for more details on this.

Also, SEH has "first-chance" handling, which allows you to log or otherwise handle the exception before unwinding destroys all the local variables.

Solution 2:

I recently had a problem which was caused indirectly by SEH, specifically because of one feature of SEH which I think every developer should be aware of:

When SEH is used destructors are not called, so if you have cleanup code in your destructor it will not be cleaned up.

Our problem was caused by a Critical Section that was wrapped by an object with Lock in the constructor and Unlock in the destructor.

We had a deadlock situation and couldn't figure out why, and after about a week of digging through the code and dumps and debugging we finally understood it was because there was an exception that was handled by COM and causing the Critical section to stay locked. We changed a compilation flag in VS in the project properties which tell it to run destructors even for SEH and that solved the problem.

So even though you may not use SEH in your code, you may be using a library that does (like COM) and that can cause unexpected behavior.

Solution 3:

They should know that they are not part of Standard C++ - they are Microsoft invention and can be used in languages other than C++.

Solution 4:

A Crash Course on the Depths of Win32™ Structured Exception Handling

That article is the reference on getting up to speed with SEH. 13 years later, is still the best there is.

There is a dedicated topic on MSDN for SEH vs. C++ Exception Handling Differences.

Some things a C++ developer should know if SEH is being discussed:

Writing C/C++ SEH Exception Handlers:

__try 
{
   // guarded code
}
__except ( expression )
{
   // exception handler code
}

This is not C++ exception handling, is the MS specific extensions for hooking straight inot SEH. It works very differently from your run-of-the-mill C++ exceptions. You need a good understanding of SEH to use these.

Writing C/C++ SEH Termination Handlers:

__try {
   // guarded code
}
__finally {
   // termination code
}

Same as with the SEH handler, do not confuse this with C++ exception semantics. You need a good understanding of SEH.

_set_se_translator: this is the function that translates SEH exceptions into C++ type exceptions when asynchronous exceptions are used /EHa.

And finally, a personal opinion: should a C++ developer know SEH? After your first rookie .ecxr you'll understand that when the push come to shove C++ exceptions are just an illusion provided for your convenience. The only thing going on is SEH.

Solution 5:

An important point is knowing when to use SEH and when to use standard C++ exceptions. First, choose only one system – mixing systems tends to be problematic, requiring a deep understanding of both to implement well. Second, at a high level, SEH is not limited to C++, while standard C++ exceptions are not limited to Windows. If this does not dictate your decision, choose standard exceptions unless they are inadequate (see the other answers for more details about what SEH can do).

A quote from Microsoft's documentation (dated 08/13/2018) supports this conclusion.

Structured exception handling (SEH) is a Microsoft extension to C to handle certain exceptional code situations, such as hardware faults, gracefully. Although Windows and Microsoft C++ support SEH, we recommend that you use ISO-standard C++ exception handling because it makes your code more portable and flexible. Nevertheless, to maintain existing code or for particular kinds of programs, you still might have to use SEH.

Why would the author of an extension recommend it not be used in most cases? Presumably because the extension was written for C and the current context is C++. The languages are similar, so porting SEH to C++ as a side-benefit was probably easy enough, even though only "particular kinds of programs" would truly benefit. (Or possibly some other reason; maybe the porting was started before C++ was standardized. History gets convoluted.)