tags:

views:

151

answers:

5

Can someone explain the difference between a C++ exception and a structured exception in MFC?

+4  A: 

A C++ exception is a feature of the programming language C++. A structured exception is a different concept of the Windows operating system. These two use similar syntax, but are technically different. Windows structured exceptions are not only usable with C++ but also e.g. with C.

Sometimes a solution to unify the handling of both: In a Windows application you can provide a handler function, which catches all structured exceptions and throws a C++ exception (defined by you).

ur
+2  A: 

Both provide mechanisms for stack unwinding when errors occur.

Structured exceptions are provided by Windows, with support from the kernel. They are raised by Windows if you do things like access an invalid memory location. They also are used to support features like automatic stack growth. They're used fairly rarely by themselves, but language exceptions in C++, .NET, and similar languages are often built on top of them. You use special keywords like __try and __catch to deal with these exceptions. However, dealing with them is comparatively difficult and error-prone, because you can break features like automatic stack expansion, as well as potentially breaking C++ language exceptions.

C++ exceptions are specified by the C++ language. The data types that is thrown and caught are C++ objects (including the possibility of primitive types). The compiler and runtime implements these on top of the underlying structured exception mechanism. This is what you get if you use the try, catch and throw keywords of the C++ language.

SEH exceptions have more features than C++ exceptions, like supporting resumption, and so-called "vectored" handlers (which receive notifications of exceptions, but don't necessarily prevent stack unwinding), but unless you specifically know you want to use them, I'd avoid them. Probably the most common use of them is to write a crash dump using MiniDumpWriteDump if your program does something illegal or undefined.

Doug
+5  A: 

You actually have three mechanisms:

  • C++ exceptions, implemented by the compiler (try/catch)
  • Structured Exception Handling (SEH), provided by Windows (__try / __catch)
  • MFC exception macros (TRY, CATCH - built on top of SEH / C++ exceptions - see also TheUndeadFish's comment)

C++ exceptions usually guarantee automatic cleanup during stack unwinding (i.e. destructors of local objects run), the other mechanisms don't.

C++ exceptions only occur when they are explicitely thrown. Structured Exceptions may occur for any operation.

MFC did introduce the exception macros to support exceptions even if compilers didn't implement them.

peterchen
Just for the sake of curiosity, MFC were ever intended to work on any compiler other than VC++?
Matteo Italia
C++ exceptions are not required to guarantee cleanup. Compile with /EHa.
Hans Passant
MFC did work on Watcom C/C++ 10. Somehow. Without the wizards and stuff.
peterchen
@Hans - umm, really? /EHa vs. /EHs does only affect whether structured exceptions are caught by a C++ exception handler. I'm pretty sure the C++ standard *guarantees* cleanup for C++ exceptions (leaving this implementaiton-defined makes no sense, as the necessary code would be fundamentally different).
peterchen
Its interesting @peterchen has seen MFC work with a non VC compiler. MFC, when its all boiled down, is a set of classes and macros that build upon the Win32 C API so it should have been compilable by non-VC compilers but I doubt this was intended. Aside: If you dig deep enough into the MFC source code you can learn a lot about how to wrap the windows message loop to meet custom needs.
mcdave
Wile MFC's exceptions used different methods in the past (before VC supported C++ exceptions, I think), MFC's exceptions are now built on top of C++ exceptions. It's in fact quite possible to convert from the MFC macros to C++ try/catch, as explained here: http://msdn.microsoft.com/en-us/library/19z28s5c.aspx So underneath it all, there are really just 2 distinct types: C++ exceptions and SEH.
TheUndeadFish
@mcdave: I'm probably showing my age :)
peterchen
Thanks to all who have contributed. :)
Krishnan
@TheUndeadFish: Thanks for the upate, I still want to keep it listed because it's a 3rd set of syntax and rules how to handle exceptions.
peterchen
+1  A: 

C++ exceptions will work cross platform. Unfortunately SEH will severly restrict portability (except may be across different Windows versions).

Also SEH seems to capture lots of native Windows exceptions (like Access Violation, An Invalid handle was specified) etc.

Chubsdad
+1  A: 

It is a heavy implementation detail, but on Windows a C++ exception is also a SEH exception. The exception code is 0xE04D5343 (last three bytes = 'MSC'). And all of the regular SEH support is used to unwind the stack, get automatic cleanup code to run and to filter the exception so the proper catch clause is selected. Getting the thrown exception object in the filter expression is plumbing that's added by the CRT beyond what SEH provides. SEH also supports a __finally clause but that doesn't get used in standard C++.

A further implementation detail is the /EH compiler setting. The default (/EHsc) allows the compiler to optimize the code that's generated and suppress the exception filters that are needed to run automatic cleanup. If it can see that none of the emitted C++ code can throw an exception. This is above all a space optimization, a small time optimization for x86 code but not for x64 code. To get automatic cleanup for SEH exceptions you have to compile with /EHa so that this optimization is suppressed.

A good strategy to marry C++ exceptions with SEH is to use _set_se_translator() so you can translate an SEH exception to a C++ exception. Albeit that it isn't often wise to catch SEH exceptions, they are almost always nasty.

Hans Passant