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

5

54

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

Pigeonwing answered 6/5, 2010 at 17:1 Comment(0)
K
50

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.

Kraul answered 6/5, 2010 at 17:2 Comment(4)
Note though that the default was changed away from handling SEH exceptions like C++ exceptions because SEH exceptions are not safe to handle like C++ exceptions. SEH exceptions are usually things like access violations, and attempting to do C++ unwinding under such conditions is not possible and can cause the program to terminate.Taking
There's nothing inherently unsafe about unwinding an access violation. Of course, if the access violation was caused by corruption of internal data structures (especially stack overflows which affect the call stack information) then unwinding is likely to fail, but many, if not the majority, of SEH exceptions don't actually reflect stack corruption.Kraul
Please also read #4414527 about a nasty side effect of SEH with ignored ellipsis-Exceptions (e.g. catch(...) {})Pyrometer
Quite important for C++ developers: Don't mix C++ exception handling and SEH (unless you absolutely know, what you are doing, and have a good reason to).Abyssal
K
39

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

Not all C++ implementations for Windows call destructors during SEH stack unwinding, so if you have cleanup code in your destructor it may 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.

Kura answered 6/5, 2010 at 17:2 Comment(0)
J
27

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.

Jeanettajeanette answered 6/5, 2010 at 17:2 Comment(3)
__finally doesn't have ( expression )Mooneye
Your Crash Course link is dead. Here is an alternative: www-user.tu-chemnitz.de/~heha/viewchm.php/hs/Win32SEH.chm/…Alibi
The current link: www-user.tu-chemnitz.de/~heha/hsn/chm/Win32SEH.chmOppressive
M
24

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

Meltage answered 6/5, 2010 at 17:2 Comment(0)
B
1

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.)

Bevon answered 6/5, 2010 at 17:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.