|
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).
|