Recoverable Internal Errors
Recoverable internal errors are similar to their non-recoverable relatives because they are easy to predict and occur at low levels.
They differ in that they are
not costly to detect
detected in both the debug
and the production versions of the library
A bounds error in a linked list or an attempt to use an invalid date are both examples of recoverable internal errors. The library's response to these errors is to throw an exception inheriting from
RWInternalErr, using the macro
RWTHROW.
The production version of the library can check for recoverable internal errors because the cost is relatively low. For example, to find a bounds error in a linked list, the cost of walking the list far exceeds the cost of detecting whether the index is in bounds. Hence, you can afford to check for a bounds error on every access.
If an error is discovered, the library throws an exception inheriting from
RWInternalErr, as we have mentioned. Following is an example:
// Find link "i"; the index must be in range:
RWIsvSlink* RWIsvSlist::at(size_t i) const
{
if (i >= entries()){
if(RW_NPOS == i)
RWTHROW( RWBoundsErr("NPOS index"));
else
RWTHROW( RWBoundsErr("Index out of bound"));
}
register RWIsvSlink* link = head_.next_;
while (i--) link = link->next_;
return link;
}
In this code, note how the function
always attempts to detect a bounds error. If it finds one, it throws an instance of
RWBoundsErr, a class that inherits from
RWInternalErr.
Throwing an exception gives you the opportunity to catch and possibly recover the exception. However, because the internal logic of the program has been compromised, you should attempt to save the document you are working on, and abort the program.