Handling Errors

In Concert Technology two kinds of errors are distinguished:

  1. Programming errors, such as:

Such errors are usually an oversight of the programmer. Once they are recognized and fixed there is usually no danger of corrupting an application. In a production version, it is not necessary to handle these kinds of errors.

In Concert Technology such error conditions are handled using assert statements. If compiled without -DNDEBUG, the error check is performed and the code aborts with an error message indicating which assertion failed. A production version should then be compiled with the -DNDEBUG compiler option, which removes all the checking. In other words, no CPU cycles are consumed for checking the assertions.
  1. Runtime errors, such as memory exhaustion.

A correct program assumes that such failures can occur and therefore must be treated, even in a production version. In Concert Technology, if such an error condition occurs, an exception is thrown.

All exceptions thrown by Concert Technology classes (including IloCplex) are derived from IloException. Exceptions thrown by algorithm classes such as IloCplex are derived from its child class IloAlgorithm::Exception. The most common exceptions thrown by CPLEX are derived from IloCplex::Exception, a child class of IloAlgorithm::Exception.

Objects of the exception class IloCplex::Exception correspond to the error codes generated by the C Callable Library. The error code can be queried from a caught exception by calling method:

IloInt IloCplex::Exception::getStatus() const; 

The error message can be queried by calling method:

const char* IloException::getMessage() const; 

which is a virtual method inherited from the base class IloException. If you want to access only the message for printing to a channel or output stream, it is more convenient to use the overloaded output operator (operator<<) provided by Concert Technology for IloException.

In addition to exceptions corresponding to error codes from the C Callable Library, a cplex object may throw exceptions pertaining only to IloCplex. For example, the exception IloCplex::MultipleObjException is thrown if a model is extracted containing more than one objective function. Such additional exception classes are derived from class IloCplex::Exception; objects can be recognized by a negative status code returned when calling method getStatus().

In contrast to most other Concert Technology classes, exception classes are not handle classes. Thus, the correct type of an exception is lost if it is caught by value rather than by reference (that is, using catch(IloException& e) {...}). This is one reason that we suggest catching IloException objects by reference, as demonstrated in all examples. See, for example, ilodiet.cpp. Some derived exceptions may carry information that would be lost if caught by value. So if you output an exception caught by reference, you may get a more precise message than when outputting the same exception caught by value.

There is a second reason for catching exceptions by reference. Some exceptions contain arrays to communicate the reason for the failure to the calling function. If this information were lost by calling the exception by value, method end() could not be called for such arrays and their memory would be leaked (until env.end() is called). After catching an expression by reference, calling the exception's method end() will free all the memory that may be used by arrays (or expressions) of the actual exception that was thrown.

In summary, the preferred way of catching an exception is:

catch (IloException& e) {
  ...
  e.end();
}

where IloException may be substituted for the desired Concert Technology exception class.


Previous Page: Changing Variable Type  Return to Top Next Page: Example: Dietary Optimization