![]() |
TRY | Language Extension |
error.h |
Starts a protected block of code.
TRY,
ONERR,
ENDTRY,
FINALLY,
ENDFINAL, and
PASS
are macros which extend the C language to implement an error handling mechanism which is
almost identical to the commonly-used exception handling as well as error handling in TI-Basic.
TRY begins the protected block. It is a macro which is implemented using the
ER_catch function. If an error occurs in the protected block, program
execution transfers to the block after the ONERR or
FINALLY statement.
However, ONERR and FINALLY
are entirely different. The ONERR block will not
be executed if there was no error, and it is assumed to either handle the
error or call PASS. The error is cleared, so if
PASS is not called, the execution continues
normally after the ENDTRY statement.
FINALLY, on the other hand, is not implemented
to handle errors, but instead to create a block of code which will always be
executed, regardless of whether there was an error or not. It does not clear
the error (or more precisely, ENDFINAL throws
it again). This can be used in a function which allocates memory, destroys
the contents of the screen, or does something else which always needs cleaning up.
If the function throws an error in a protected block, the memory should
always be freed again, the screen should be restored, etc. But the error
should not be handled at the same time; instead, it must be handled on a
higher level (often even in the calling function).
The usage of ONERR is illustrated in the following example:
TRY // <protected code> ONERR if (errCode == some_specific_code) // <error handler> else // pass on any unhandled errors to a higher level PASS; ENDTRYThe usage of FINALLY is illustrated in the following example:
TRY ... // <allocate memory> TRY // <protected code> FINALLY // <free the allocated memory> ENDFINAL ... ONERR // <error handler> ENDTRYThe variable errCode is automatically created in the error handler, and it contains the error number to allow the program to check what caused the error. This variable will be destroyed after the ENDTRY/ENDFINAL statement.
TRY ... if (I_really_must_exit_from_here) { ER_success (); return; } ... ONERR ... ENDTRYBut in general this is a very bad practice and should be avoided even if it requires some extra code. For example, you can rewrite the code like this:
TRY ... if (!I_really_must_exit_from_here) { ... } ONERR ... ENDTRY if (I_really_must_exit_from_here) return;There is also another possible caveat related to error handling. The TRY macro (or ER_catch, more precisely) saves many of the registers on its execution context stack, since ER_catch needs to simulate a return identical to the return of any normal function. Consequently, when an error is thrown, all variables which reside in registers are reset to their contents before the TRY macro was called. If code in an ONERR or FINALLY block needs the value of a variable set in the TRY block, the code must arrange to make sure the C code optimizer does not put that variable in a register. This can be accomplished by declaring such variables to be volatile. So, remember this rule: Variables changed in a TRY block must be declared volatile if they are referenced in an ONERR or FINALLY block!
ENABLE_ERROR_RETURN
instead of using a
TRY...ONERR...ENDTRY block.
See the section Returning Errors
for more information.