try-except Statement

Microsoft Specific —>

The try-except statement is a Microsoft extension to the C and C++ languages that enables 32-bit target applications to gain control when events that normally terminate program execution occur. Such events are called exceptions, and the mechanism that deals with exceptions is called structured exception handling.

For related information, see the try-finally statement. For more information on structured exception handling in general, see Exception Handling Topics (SEH).

Exceptions can be either hardware-based or software-based. Even when applications cannot completely recover from hardware or software exceptions, structured exception handling makes it possible to display error information and trap the internal state of the application to help diagnose the problem. This is especially useful for intermittent problems that cannot be reproduced easily.

Note   Structured exception handling works with Win32 for both C and C++ source files. However, it is 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, it is recommended that you use the new C++ exception-handling mechanism (try, catch, and throw statements).

try-except-statement :
__try compound-statement
__except ( expression ) compound-statement

The compound statement after the __try clause is the body or guarded section. The compound statement after the __except clause is the exception handler. The handler specifies a set of actions to be taken if an exception is raised during execution of the body of the guarded section. Execution proceeds as follows:

  1. The guarded section is executed.

  2. If no exception occurs during execution of the guarded section, execution continues at the statement after the __except clause.

  3. If an exception occurs during execution of the guarded section or in any routine the guarded section calls, the __except expression is evaluated and the value determines how the exception is handled. There are three values:

    EXCEPTION_CONTINUE_EXECUTION (–1)   Exception is dismissed. Continue execution at the point where the exception occurred.

    EXCEPTION_CONTINUE_SEARCH (0)   Exception is not recognized. Continue to search up the stack for a handler, first for containing try-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 at the assembly instruction that was executing when the exception was raised.

Because the __except expression is evaluated as a C expression, it is 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. The __except expression executes in the scope of the __try body. This means it has access to any local variables declared there.

It is illegal to jump into a __try statement, but legal to jump out of one. The exception handler is not called if a process is killed in the middle of executing a try-except statement.

Structured Exception Handling Intrinsic Functions

The structured exception handling feature provides two intrinsics that are available for use with the try-except statement. These are _exception_code and _exception_info.

The intrinsic function _exception_code returns the code (a 32-bit integer) of the exception.

The intrinsic function _exception_info returns a pointer to a 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:

struct exception_pointers {
      EXCEPTION_RECORD *ExceptionRecord,
      CONTEXT *ContextRecord }

The pointer types _EXCEPTION_RECORD and _CONTEXT are defined in the include file EXCPT.H.

You can use the _exception_code function within the exception handler. However, you can use _exception_info only within the exception filter. The information it points to is generally on the stack and is wiped out when control is transferred to the exception handler.

The intrinsic function _abnormal_termination 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.

END Microsoft Specific

Example

// Example of try-except and try-finally statements
#include "stdio.h"

void 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");
      }
   }__except(puts("in filter"), 1){
      puts("in except");
   }
   puts("world");
}

This is the output from the example, with commentary added on the right:

hello
in try         //fall into try
in try         //fall into nested try
in filter      //execute filter; returns 1 so accept
in finally     //unwind nested finally
in except      //transfer control to selected handler
world          //flow out of handler