Rogue Wave banner
Previous fileTop of DocumentContentsIndex pageNext file
Essential Math Module User's Guide
Rogue Wave web site:  Home Page  |  Main Documentation Page

8.1 Errors

Bad things can happen even to good programs. When they do, you must confront the potentially messy, unpredictable, and painful topic of error handling. You can take some consolation in knowing that every developer goes through it. Also, the Rogue Wave class libraries use an extensive and complete error handling model to alleviate your distress.

In the Essential Math Module, errors are divided into three categories:

The difference between them depends on who made the error: the programmer, the final end user, or some external/internal software error. Each type of error requires a different type of handling. The following sections describe these approaches and when you can change how they are handled.

8.1.1 Violated Preconditions

Violated precondition errors involve failures to follow the programming rules set out by the Essential Math Module classes. If an indexing operator says not to ask for an index greater than a vector's length and you do so anyway, that is a violated precondition.

A more formal description is given by Meyer (1988). In summary, Meyer says that a function is regarded as a contract between the caller and the callee. If the caller abides by a set of preconditions, then the callee guarantees to return results that satisfy a set of postconditions. Typically, preconditions are such things as requiring that an index be within a set of bounds, that pointers be non-nil, and so on. The ideal goal is that these types of errors never happen. If they never happen, there is no need to provide a recovery mechanism or even to detect them!

But, of course, they do happen. So, how do you guard against them? And how do you detect them? The Rogue Wave classes have an extensive set of PRECONDITION and POSTCONDITION clauses at the beginning and end of critical functions. They can be activated by compiling the entire library with the preprocessor flag RW_DEBUG defined.


The entire library must be compiled with a single setting of the flag—either defined or not defined.

If compiled with the RW_DEBUG flag defined, the resultant library will be slightly larger and slightly slower. See the appropriate makefile for additional directions.

The preconditions and postconditions are implemented either through the Rogue Wave error facility or with asserts. With asserts, a failure causes the offending condition to be printed out, along with the file and line number where it occurred.

Again, the assumption is that these are programming errors and can and should be avoided. Hence, there are no facilities for error recovery.

8.1.2 Invalid Input

An invalid input error is usually caused by the final end user. For example, you might use class RWGenFact<T> to construct an LU factorization from a matrix that turns out to be singular. It is a mean-spirited program that simply aborts when given such a matrix. It is preferable if the factorization's validity can be explicitly checked, to be rejected or corrected.

The line between a violated precondition and an invalid input can be unclear. For example, the rules could say, "Don't give me a singular matrix," and then the programmer is responsible for detecting the matrix's singularity before handing it to the RWGenFact<T> constructor. Of course, this is a lot of work, and in this example the RWGenFact<T> class is better equipped than the caller to determine the singularity of the matrix. Hence, this is an approach that is generally not taken.

How are these kinds of errors dealt with? Generally, either by returning a special value, such as a nil pointer, or by using a member function that tests the validity of the resultant object. The following code continues the RWGenFact<T> example:

The above program prints out Non factorable matrix. Like many other classes, class RWGenFact<T> has several member functions for testing its validity.

8.1.3 Asynchronous Errors

Difficult to predict, asynchronous errors are generally due to a failure on the part of the operating system. By far the most common example is "out of memory." Other asynchronous errors are failure to open a file, perhaps due to lack of disk space, or hardware failure.

The usual response to these types of errors by the Essential Math Module is to throw an exception. If exceptions are not available, the default error handler posts a note to standard output with the type of error, then aborts the program. This default handler can be changed.

8.1.4 Exception Hierarchy

When an exception is thrown, a throw operand is passed. The type of the throw operand determines which handlers can catch it. The Essential Math Module uses the following hierarchy for throw operands:

xmsg
     RWxmsg
          RWInternalErr
               RWBoundsErr
          RWExternalErr
               RWFileErr
               RWStreamErr
     xalloc
          RWxalloc

This hierarchy assumes the presence of class xmsg, nominally provided by your compiler vendor. Class xmsg carries a string that can be printed out at the catch site to give you some idea of what went wrong. This string can be formatted and internationalized as described in the Essential Tools Module User's Guide chapter on internationalization. If your compiler does not come with versions of xmsg and xalloc, the Rogue Wave classes RWxmsg and RWxalloc can emulate them for you.

8.1.5 Error Handlers

The Essential Math Module uses the macro RWTHROW to throw an exception. If your compiler supports exceptions, this macro resolves by calling a function that throws the exception. If your compiler does not support exceptions, the macro resolves to call an error handler with prototype:

The default error handler aborts the program. You can change the default handler with the function:

The next example demonstrates how a user-defined error handler works in a compiler that doesn't support exceptions:

8.1.6 Error Numbers and Messages

The error numbers are listed in the header files <rw/coreerr.h> and <rw/matherr.h>. You can see the associated error messages and auxiliary information in files coreerr.cpp and matherr.cpp, and surmise the auxiliary information contained in the va_list. For example, the error RWMATH_INDEX is listed in matherr.cpp as:

The first argument in the va_list is the index the user attempted to use, and the second is the highest allowed index.



Previous fileTop of DocumentContentsNo linkNext file

Copyright © Rogue Wave Software, Inc. All Rights Reserved.

The Rogue Wave name and logo, and SourcePro, are registered trademarks of Rogue Wave Software. All other trademarks are the property of their respective owners.
Provide feedback to Rogue Wave about its documentation.