ErrDisplay
,
ErrFatalDisplayIf
, and
ErrNonFatalDisplayIf
.
ErrDisplay
always displays the error message on the screen.ErrFatalDisplayIf
and
ErrNonFatalDisplayIf
display the error message only if their first argument is TRUE.
ERROR_CHECK_LEVEL
to control the level of error messages displayed. You can set the value of the compiler define to control which level of error checking and display is compiled into the application. Three levels of error checking are supported: none, partial, and full.
true
to display the error, and a pointer to a text message to display if the condition is true.
true
if there is an error condition. As a result, both the expression that evaluates the error condition and the message text are left out of the compiled code when error checking is turned off. You can call
ErrFatalDisplayIf
, or
ErrDisplay
, but using ErrFatalDisplayIf
makes your source code look neater.
result = DoSomething();
ErrFatalDisplayIf (result < 0,
"unexpected result from DoSomething");
DoSomething()
is less than 0. Besides the error message itself, this alert also shows the file name and line number of the source code that called the error manager. With error checking turned off, both the expression evaluation err < 0
and the error message text are left out of the compiled code.
result = DoSomething();
#if ERROR_CHECK_LEVEL != ERROR_CHECK_NONE
if (result < 0)
    ErrDisplay ("unexpected result from DoSomething");
#endif
ErrFatalDisplayIf
. It also makes the source code harder to follow.
goto
if an error occurs. A typical way of handling errors in the middle of a routine is to go to the end of the routine as soon as an error occurs and have some general-purpose cleanup code at the end of every routine. Errors in nested routines are even trickier because the result code from every subroutine call must be checked before continuing.
ErrThrow
. When the compiler sees the ErrThrow call, it performs a goto
to your error handling code. The greatest advantage to calling ErrThrow, however, is for handling errors in nested subroutine calls.
is called from a nested subroutine, execution immediately goes to the same error handling code in the higher-level call. The compiler and runtime environment automatically strip off the stack frames that were pushed onto the stack during the nesting process and go to the error handling section of the higher-level call. You no longer have to check for result codes after calling every subroutine; this greatly simplifies your source code and reduces its size.
    ErrTry {
p = MemPtrNew(1000);
    if (!p) ErrThrow(errNoMemory);
    MemSet(p, 1000, 0);
    CreateTable(p);
    PrintTable(p);
}
ErrCatch(err) {
// Recover or clean up after a failure in the
// above Try block."err" is an int
// identifying the reason for the failure.
// You may call ErrThrow() if you want to
// jump out to the next Catch block.
// The code in this Catch block doesn't
// execute if the above Try block completes
    // without a Throw.
    if (err == errNoMemory)
    ErrDisplay("Out of Memory");
    else
    ErrDisplay("Some other error");
} ErrEndCatch
    // You must structure your code exactly as
// above. You can't have an ErrTry without an
    //ErrCatch { } ErrEndCatch, or vice versa.
ErrTry
block results in control passing immediately to the ErrCatch
block. Even if the subroutine CreateTable
called ErrThrow, control would pass directly to the ErrCatch
block. If the ErrTry
block completes without calling ErrThrow
, the ErrCatch
block is not executed.
ErrTry
blocks. For example, if you wanted to perform some cleanup at the end of CreateTable
in case of error,
Error Manager Functions | |
---|---|
ErrDisplay | ErrDisplayFileLineMsg |
ErrFatalDisplayIf | ErrNonFatalDisplayIf |
ErrThrow | ErrAlert |
  |   |