Contributor's Corner

A collection of hopefully helpful information
Functionality Clarity Elegance

  C++ Exceptions   

Concepts & Techniques

Rule One:
View exception handling as part of an error management strategy

Exceptions are not the only way of handling or reporting error conditions. Other ways include;
  1. When an error condition is detected, simply exit the program. This approach is often used in C programs when dynamic memory allocation fails.
  2. Use return or error codes from functions rather than exceptions. This approach is commonly used in C and C++ for errors that occur with file input and output.
Both of these approaches may be used, whether exceptions are used or not. The first approach is common in C programs as C does not support exceptions, but less common in well-designed C++ code as an unhandled exception gives the same effect, but also provides an opportunity to catch and recover from the error. The second approach is appropriate if the error condition is not severe. This is a double edged sword, as it requires the caller to deliberately check if an error has occurred, but the error will be silently ignored if the caller forgets to do that check. An error code is therefore appropriate if the program can sensibly continue executing even if the error code is not checked. An example where error codes are appropriately used is "end of file" (EOF) condition with C and C++ file input. This allows parsing of a file using a loop that repeats until EOF is reached. Forgetting to check for EOF is also rarely a critical error (the program can often continue sensibly afterwards). One of my pet peeves with the Java I/O library is that it throws exceptions for some non-critical errors, forcing code that reads from a file to be more complex (several local try/catch blocks) than necessary. It often makes sense to handle errors by different mechanisms. There is nothing wrong with a program that makes use of multiple error reporting mechanisms. Essentially, the errors encountered by an application fall into four categories.
  1. Those that can be recovered from immediately, by the code that detects them.
  2. Those that cannot be recovered from immediately, but do not cause chaos if they are ignored.
  3. Those that cannot be recovered from immediately, but will cause chaos if recovery is not initiated.
  4. Those that are irrecoverable.
An example of the first would be a function that dereferences a pointer detecting that the pointer is NULL. Such an error might be recovered from silently by doing nothing if the pointer is NULL. This would only be appropriate if behaviour of other code will not be adversely affected by our function silently takes no action. An example of the second is file I/O. Encountering an EOF is often an expected, and non-critical, event when reading a file. An example of the third category is a function that detects failure of supplied data to comply with a complex set of required pre-conditions, but has insufficient information to be able to correct the data. Throwing an exception is appropriate to return control to a caller that (presumably) provided the required data. To develop a useful error handling strategy, it is necessary to characterise the severity of errors, the urgency and feasibility of recovery, and whether or not it is possible to correct an error at the point it is detected. If a particular error falls neatly into one of the categories above, the approach to handle that error will be obvious. A lot of errors will not fall neatly into only one category. In this case, an analysis of of benefits and costs will determine options to realistically handle the error.

 Exception Basics & FeaturesConcepts & Techniques: Rule Two