try-except
statement
The try-except
statement is a Microsoft-specific extension that supports structured exception handling in the C and C++ languages.
// . . .
__try {
// guarded code
}
__except ( /* filter expression */ ) {
// termination code
}
// . . .
Grammar
try-except-statement
:
__try
compound-statement
__except (
expression
)
compound-statement
Remarks
The try-except
statement is a Microsoft extension to the C and C++ languages. It enables target applications to gain control when events occur that normally terminate program execution. Such events are called structured exceptions, or exceptions for short. The mechanism that deals with these exceptions is called structured exception handling (SEH).
For related information, see the try-finally statement.
Exceptions may be either hardware-based or software-based. Structured exception handling is useful even when applications can't completely recover from hardware or software exceptions. SEH makes it possible to display error information and trap the internal state of the application to help diagnose the problem. It's especially useful for intermittent problems that aren't easy to reproduce.
Note
Structured exception handling works with Win32 for both C and C++ source files. However, it's not specifically designed for C++. You can ensure that your code is more portable by using C++ exception handling. Also, C++ exception handling is more flexible, in that it can handle exceptions of any type. For C++ programs, we recommend you use native C++ exception-handling: try, catch, and throw statements.
The compound statement after the __try
clause is the body or guarded section. The __except
expression is also known as the filter expression. Its value determines how the exception is handled. The compound statement after the __except
clause is the exception handler. The handler specifies the actions to take if an exception is raised during execution of the body section. Execution proceeds as follows:
The guarded section is executed.
If no exception occurs during execution of the guarded section, execution continues at the statement after the
__except
clause.If an exception occurs during execution of the guarded section, or in any routine the guarded section calls, the
__except
expression is evaluated. There are three possible values:EXCEPTION_CONTINUE_EXECUTION
(-1) Exception is dismissed. Continue execution at the point where the exception occurred.EXCEPTION_CONTINUE_SEARCH
(0) Exception isn't recognized. Continue to search up the stack for a handler, first for containingtry-except
statements, then for handlers with the next highest precedence.EXCEPTION_EXECUTE_HANDLER
(1) Exception is recognized. Transfer control to the exception handler by executing the__except
compound statement, then continue execution after the__except
block.
The __except
expression is evaluated as a C expression. It's limited to a single value, the conditional-expression operator, or the comma operator. If more extensive processing is required, the expression can call a routine that returns one of the three values listed above.
Each application can have its own exception handler.
It's not valid to jump into a __try
statement, but valid to jump out of one. The exception handler isn't called if a process is terminated in the middle of executing a try-except
statement.
For compatibility with previous versions, _try, _except, and _leave are synonyms for __try
, __except
, and __leave
unless compiler option /Za (Disable language extensions) is specified.
The __leave
keyword
The __leave
keyword is valid only within the guarded section of a try-except
statement, and its effect is to jump to the end of the guarded section. Execution continues at the first statement after the exception handler.
A goto
statement can also jump out of the guarded section, and it doesn't degrade performance as it does in a try-finally statement. That's because stack unwinding doesn't occur. However, we recommend that you use the __leave
keyword rather than a goto
statement. The reason is because you're less likely to make a programming mistake if the guarded section is large or complex.
Structured exception handling intrinsic functions
Structured exception handling provides two intrinsic functions that are available to use with the try-except
statement: GetExceptionCode and GetExceptionInformation.
GetExceptionCode
returns the code (a 32-bit integer) of the exception.
The intrinsic function GetExceptionInformation
returns a pointer to an EXCEPTION_POINTERS structure containing additional information about the exception. Through this pointer, you can access the machine state that existed at the time of a hardware exception. The structure is as follows:
typedef struct _EXCEPTION_POINTERS {
PEXCEPTION_RECORD ExceptionRecord;
PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
The pointer types PEXCEPTION_RECORD
and PCONTEXT
are defined in the include file <winnt.h>, and _EXCEPTION_RECORD
and _CONTEXT
are defined in the include file <excpt.h>
You can use GetExceptionCode
within the exception handler. However, you can use GetExceptionInformation
only within the exception filter expression. The information it points to is generally on the stack and is no longer available when control gets transferred to the exception handler.
The intrinsic function AbnormalTermination is available within a termination handler. It returns 0 if the body of the try-finally statement terminates sequentially. In all other cases, it returns 1.
<excpt.h> defines some alternate names for these intrinsics:
GetExceptionCode
is equivalent to _exception_code
GetExceptionInformation
is equivalent to _exception_info
AbnormalTermination
is equivalent to _abnormal_termination
Example
// exceptions_try_except_Statement.cpp
// Example of try-except and try-finally statements
#include <stdio.h>
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>
int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
puts("in filter.");
if (code == EXCEPTION_ACCESS_VIOLATION)
{
puts("caught AV as expected.");
return EXCEPTION_EXECUTE_HANDLER;
}
else
{
puts("didn't catch AV, unexpected.");
return EXCEPTION_CONTINUE_SEARCH;
};
}
int main()
{
int* p = 0x00000000; // pointer to NULL
puts("hello");
__try
{
puts("in try");
__try
{
puts("in try");
*p = 13; // causes an access violation exception;
}
__finally
{
puts("in finally. termination: ");
puts(AbnormalTermination() ? "\tabnormal" : "\tnormal");
}
}
__except(filter(GetExceptionCode(), GetExceptionInformation()))
{
puts("in except");
}
puts("world");
}
Output
hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
abnormal
in except
world
See also
Writing an exception handler
Structured Exception Handling (C/C++)
Keywords