Exception Handling Macros
List of: Discussion Topic
Subjects: Error Handling
Contents: Application Development Manual

Four macros have been defined to allow ACIS code to take corrective action if an error or interrupt occurs. Applications may also need to use these when using the ACIS direct function or class interfaces (i.e., non-APIs). The four exception handling macros are:

EXCEPTION_BEGIN

// Declarations of local variables to be cleaned up go here
EXCEPTION_TRY

// Normal processing code goes here
EXCEPTION_CATCH(always_clean)

// Interrupt/error cleanup code goes here
EXCEPTION_CATCH_FALSE

// logically the same as EXCEPTION_CATCH(FALSE)

// but it does not cause a warning about using a

// constant expression in an if statement.
EXCEPTION_CATCH_TRUE

// logically the same as EXCEPTION_CATCH(TRUE)

// but it does not cause a warning about using a

// constant expression in an if statement.
EXCEPTION_END_NO_RESIGNAL

// logically the same as resignal_no = 0;
EXCEPTION_END

The macros must appear in the order specified above (BEGIN, TRY, CATCH, END). The EXCEPTION_CATCH macro is optional and may be omitted if only local variables are to be cleaned up. Sets of macros may be nested, but they must not overlap. The inner set must be fully contained between adjacent macros (normally between EXCEPTION_TRY and EXCEPTION_CATCH) of the outer set.

You must select zero or one of the CATCH macros and exactly one of the END macros in each exception block. For example, you should never have an EXCEPTION_CATCH_TRUE and an EXCEPTION_CATCH_FALSE in the same block of protected code.

The macros are defined in errorsys.hxx which is included in all .err files generated from .msg files. If a file currently calls sys_error, no new header files should be needed. Otherwise, errorsys.hxx should be included.

The EXCEPTION_BEGIN block (between the EXCEPTION_BEGIN and EXCEPTION_TRY macros) is used to declare variables that must be cleaned up if an error occurs. This includes pointers to be deleted in the EXCEPTION_CATCH block as well as local instances of classes that may contain pointers to potentially large amounts of dynamically allocated memory. Local instances are automatically destroyed by block exit code in the EXCEPTION_END macro before any error is re-signalled.

Variables declared in the EXCEPTION_BEGIN block should be declared as being "volatile" so that they will not be created as register variables. This will prevent the unexpected resetting of the variables during exception handling. Similarly, variables that are declared before the EXCEPTION_BEGIN block--and whose values are changed in the EXCEPTION_TRY block and are cleaned up in the EXCEPTION_CATCH block--are candidates to be made volatile. For example:

EXCEPTION_BEGIN
myclass* volatile vm = NULL;
EXCEPTION_TRY
vm = new myclass(...);
...
EXCEPTION_CATCH(TRUE)
delete vm;
EXCEPTION_END

If multiple variables are declared in the EXCEPTION_BEGIN block, their initialization should be kept as simple as possible since any error or interrupt that occurs in this block will not cause the corresponding EXCEPTION_CATCH block to be executed nor the local variables to be destroyed.

The EXCEPTION_TRY block (between the EXCEPTION_TRY and EXCEPTION_CATCH macros) contains the normal processing code. Variables declared here are visible only within the EXCEPTION_TRY block. They are destroyed by the block exit code only if no error or interrupt occurs. Variables that need to be cleaned up if an error occurs should be declared in or before the EXCEPTION_BEGIN block. Variables that must be visible after the EXCEPTION_END macro must be declared before the EXCEPTION_BEGIN macro.

The EXCEPTION_CATCH block (between the EXCEPTION_CATCH and EXCEPTION_END macros) is used to free dynamically allocated memory and reset global variables. The always_clean argument to the EXCEPTION_CATCH macro is a logical expression used to indicate whether the EXCEPTION_CATCH block should be executed even if no error occurs. This is useful to avoid duplication of code used to free temporary memory. The variable error_no can be examined to determine what (if any) error occurred. The variable resignal_no can be modified to change the error re-signalled to higher blocks. Setting resignal_no to zero stops the error from being re-signalled.

On most platforms, the use of setjmp and longjmp (for example, in macros API_BEGIN and API_END) has been replaced with the C++try/catch statements. Some platforms do not support the try/catch statements, so ACIS uses setjmp and longjmp on those platforms (ACIS uses setjmp and longjmp if UNIX_EXCEPTION_TRAP is defined, and uses the try/catch statements if CPLUSPLUS_EXCEPTION_TRAP is defined).
PDF/APPDEV/06ERR.PDF
HTM/DATA/ACIS/APPDEV/06ERR/0003.HTM