17. Fault Handling
- Rec. 60
- Make sure that fault handling is done
so that the transfer to exception handling (when this is available in
C++) may be easily made.
- Rec. 61
- Check the fault codes which may be
received from library functions even if these functions seem foolproof.
In November 1990, the ANSI C++ committee accepted a proposal for
exception handling which is described in chapter 15 of
The Annotated C++ Reference Manual.
When designing fault handling in code, it is appropriate to consider
being able to make a smooth transfer to exception handling. For example,
instead of using ordinary fault codes, which may necessitate a lot of
re-programming when exception handling is available, a call can be made
to a function void fault(const char*) which sends a fault
message (somewhere) and then terminates execution in some way.
System functions (those which are specific to UNIX) ought to be used
with care if the code is to be portable. If such functions are used,
the possible fault codes that may be received should be carefully checked.
Two important characteristics of a robust system are that all faults
are reported and, if the fault is so serious that continued execution
is not possible, the process is terminated. In this way, the propagation
of faults through the system is avoided. It is better to have a process
crash, than to spread erroneous information to other processes. In
achieving this goal, it is important to always test fault codes from
library functions. The opening or closing of files may fail, allocation
of data may fail, etc. One test too many is better than one test too
few. Our own functions should preferably not return fault codes, but
should instead take advantage of exception handling.
Example 66: Future exception handling in C++
// The top function where we catch exceptions thrown in called functions
int f()
{
// We suspect that something can go wrong when function g() is called.
// Therefore, we enclose the call in a try block.
try
{
return g(); // This is the try block
}
// If any exceptions, having a given type, were thrown when g()
// was executing, they are caught in these two catch blocks.
catch ( int x ) // catches int
{
cerr << "Number " << x << " happened !" << endl;
return x;
}
catch ( char* x ) // catches char*
{
// Respond in some other way
}
// Anything else that is thrown, is thrown up to the function that calls f()
}
// This function has no try or catch block. When the exception is thrown
// in function h(), it is thrown up to the function f().
int g()
{
return h();
}
extern int somethingIsVeryWrongAndICannotHandleThisAnyMore();
int h()
{
// Here we find out that something went wrong, and throw an exception
if (somethingIsVeryWrongAndICannotHandleThisAnyMore())
{
// In this case, we throw an int as exception, but almost any object
// can be thrown. See Errata for "The Annotated C++ Reference Manual"
// section 15.7>.
throw 2;
}
// Keep on trucking if all is OK
}
|