On Windows, an exception is an event that occurs during the execution of a program. There are two kinds of exceptions: hardware exceptions and software exceptions. Hardware exceptions are comparable to signals such as SIGSEGV
and SIGKILL
on Oracle Solaris and Linux operating systems. Software exceptions are initiated explicitly by applications or the operating system using the RaiseException()
API.
On Windows, the mechanism for handling both hardware and software exceptions is called structured exception handling (SEH). This is stack frame-based exception handling similar to the C++ and Java exception handling mechanism. In C++ the __try
and __except
keywords are used to guard a section of code that might result in an exception, as shown in Example 7-1.
Example 7-1 Try and Except Block
__try {
// guarded body of code
} __except (filter-expression) {
// exception-handler block
}
The __except
block is filtered by a filter expression that uses the integer exception code returned by the GetExceptionCode()
API, exception information returned by the GetExceptionInformation()
API, or both.
The filter expression should evaluate to one of the following values:
EXCEPTION_CONTINUE_EXECUTION = -1
The filter expression has repaired the situation, and execution continues where the exception occurred. Unlike some exception schemes, SEH supports the resumption model as well. This is much like Unix signal handling in the sense that after the signal handler finishes, the execution continues where the program was interrupted. The difference is that the handler in this case is just the filter expression itself and not the __except
block. However, the filter expression might also involve a function call.
EXCEPTION_CONTINUE_SEARCH = 0
The current handler cannot handle this exception. Continue the handler search for the next handler. This is similar to the catch
block not matching an exception type in C++ and Java.
EXCEPTION_EXECUTE_HANDLER = 1
The current handler matches and can handle the exception. The __except
block is executed.
The __try
and __finally
keywords are used to construct a termination handler as shown in Example 7-2.
Example 7-2 Try and Finally Block
__try { // guarded body of code } __finally { // __finally block }
When control leaves the __try
block (after exception or without exception), the __finally
block is executed. Inside the __finally
block, the AbnormalTermination()
API can be called to test whether control continued after the exception or not.
Windows programs can also install a top-level unhandled exception filter function to catch exceptions that are not handled in the __try
/__except
block. This function is installed on a process-wide basis using the SetUnhandledExceptionFilter()
API. If there is no handler for an exception, then UnhandledExceptionFilter()
is called, and this will call the top-level unhandled exception filter function, if any, to catch that exception. This function also shows a message box to notify the user about the unhandled exception.
Windows exceptions are comparable to Unix synchronous signals that are attributable to the current execution stream. In Windows, asynchronous events such as console events (for example, the user pressing Control+C at the console) are handled by the console control handler registered using the SetConsoleCtlHandler()
API.
If an application uses the signal()
API on Windows, then the C runtime library (CRT) maps both Windows exceptions and console events to appropriate signals or C runtime errors. For example, CRT maps Control+C to SIGINT
and all other console events to SIGBREAK
. Similarly, if you register the SIGSEGV
handler, CRT translates the corresponding exception to a signal. CRT startup code implements a __try
/__except
block around the main()
function. The CRT's exception filter function (named _XcptFilter
) maps the Win32 exceptions to signals and dispatches signals to their appropriate handlers. If a signal's handler is set to SIG_DFL
(default handling), then _XcptFilter
calls UnhandledExceptionFilter
.
With Windows XP or Windows 2003, the vectored exception handling mechanism can also be used. Vectored handlers are not frame-based handlers. A program can register zero or more vectored exception handlers using the AddVectoredExceptionHandler
API. Vectored handlers are invoked before structured exception handlers, if any, are invoked, regardless of where the exception occurred.
Vectored exception handler returns one of the following values:
EXCEPTION_CONTINUE_EXECUTION
: Skip next vectored and SEH handlers.
EXCEPTION_CONTINUE_SEARCH
: Continue next vectored or SEH handler.
See the Microsoft web site for further information on Windows exception handling.