Exceptions and Error handling
VIP version 5.x
 | When an error/exception occur raise an exception with errorExit. |
 | Trap an exception if you want to handle the exception. |
 | Trap an exception if you want to clean up and then reexit (using exit). |
The difference between errorExit and exit is that errorExit
sets the error-state to that particular source file and position, whereas exit
leaves the state as it is. Therefore, you should use exit when you reexit
after cleaning up: the cause and source of the error has not changed.
VIP version 6.x
cErrorSystem and trap constitute the error handling system of VIP 6.x
programs.
 | When an error/exception occur raise an exception with cErrorSystem::raise |
 | Trap an exception if you want to handle the exception, if the exception is handled then
clear the error state with cErrorSystem::clear otherwise continue the error with cErrorSystem::continue. |
 | Trap an exception if you want to clean up and then reexit (using cErrorSystem::continue). |
The error system of VIP 6.x keeps track of an "error stack". The first
entry in the (normally) stack corresponds to cErrorSystem::raise, whereas the next entries
(normally) corresponds to cErrorSystem::continue. If the error is handled then
there is no longer an error and therefore the "error stack" is cleared.
If the error is not handled on its way out the "error stack" can be dumped
for debug purposes.
Internal errors and other errors (VIP 5.x and 6.x)
You should distinguish between internal errors and errors which had to do with the
usage of the tool/module/class/unit. If some internal invariant is violated it is an
internal error. Typical examples of internal errors are:
 | A database fact which should have been defined is not defined. |
 | A predicate which should be a procedure, but which the compiler could not recognize as
such are made into a procedure by adding a fall through clause, if that clause is reached
it is because the assumption that the previous clause could not fail (an invariant) was
wrong. |
Internal errors should share one error code pr. unit. You should always use an
error code: One for each user error and one for internal error (that is one for each
unit).
Typical user errors:
 | If a pane index is wrong |
 | If a window handle is wrong |
 | If the predicates are called in the wrong order. |
There are two reasons why one might want to trap an exit:
- Because one wants to handle the exit, say you open a file and get an exit saying that
the file does not exists. In that case you want to trap the exit and display some error
message saying that the file does not exists. Of course if the exit code was not one of
the ones you wanted to handle you have to re-exit with the old code.
- Because you want to do something regardless of whether the predicate exits, a typical
example is that you get some kind of lock do something and release the lock. Here you want
to be sure that the lock is released also if this something exits. So you trap, clean up
and re-exits (VIP 5.x: with the same error code using exit
instead of errorExit, VIP 6.x: using cErrorSystem::continue).
Trap examples (VIP 5.x)
Trap examples (VIP 6.x)
|