The library infrastructure » Error management module
#include "diplib.h"

Exception classes and error management functionality

Contents

Classes

class dip::Error
Base exception class. All exceptions thrown in DIPlib are derived of this class.
class dip::AssertionError
Exception class indicating that an internal inconsistency was found (the library code is wrong).
class dip::ParameterError
Exception class indicating that a function received an inconsistent or out of range parameter (the calling code is wrong).
class dip::RunTimeError
Exception class indicating that something happened that we couldn’t predict (e.g. file error).

Macros

#define DIP_ADD_STACK_TRACE
Adds information from current function (including source file and location within file) to the dip::Error.
#define DIP_THROW
Throw a dip::ParameterError.
#define DIP_THROW_INVALID_FLAG
Throw a dip::ParameterError that reads “Invalid flag: “.
#define DIP_THROW_IF
Test a condition, throw a dip::ParameterError if the condition is met.
#define DIP_THROW_RUNTIME
Throw a dip::RunTimeError.
#define DIP_THROW_ASSERTION
Throw a dip::AssertionError.
#define DIP_ASSERT
Test a condition, throw a dip::AssertionError if the condition is not met.
#define DIP_START_STACK_TRACE
Starts a try/catch block that builds a stack trace when an exception is thrown.
#define DIP_END_STACK_TRACE
Ends a try/catch block that builds a stack trace when an exception is thrown. See DIP_START_STACK_TRACE.
#define DIP_STACK_TRACE_THIS
Encapsulates a statement in a try/catch block that builds a stack trace when an exception is thrown.
#define DIP_PARALLEL_ERROR_DECLARE
Declarations needed before an OpenMP parallel section to catch exceptions.
#define DIP_PARALLEL_ERROR_START
Starts a try/catch block. Do not use without a DIP_PARALLEL_ERROR_END. See DIP_PARALLEL_ERROR_DECLARE for details.
#define DIP_PARALLEL_ERROR_END
Ends a try/catch block started by DIP_PARALLEL_ERROR_START. See DIP_PARALLEL_ERROR_DECLARE for details.

Macro documentation

#define DIP_ADD_STACK_TRACE

Adds information from current function (including source file and location within file) to the dip::Error.

This macro is useful for building a stack trace. If you want a stack trace, each function must catch dip::Error, add its name to the stack trace, and re-throw the exception.

You can use this macro as follows:

try {
   // some DIPlib functions that might throw here
}
catch( dip::Error& e ) {
   DIP_ADD_STACK_TRACE( e );
   throw;
}

The DIP_START_STACK_TRACE, DIP_END_STACK_TRACE and DIP_STACK_TRACE_THIS macros help build this code. When compiling with the CMake configuration flag DIP_ENABLE_STACK_TRACE set to OFF, these macros don’t do anything. Turn the option off if your application would make no use of the stack trace, as building the stack trace does incur some runtime cost.

#define DIP_ASSERT

Test a condition, throw a dip::AssertionError if the condition is not met.

If the CMake variable DIP_ENABLE_ASSERT is set to OFF during compilation, this macro is does nothing:

cmake -DDIP_ENABLE_ASSERT=OFF ...

You would typically disable assertions for production code, as assertions are only used to test internal consistency or detect bugs in the code.

#define DIP_START_STACK_TRACE

Starts a try/catch block that builds a stack trace when an exception is thrown.

To build a stack trace, some library functions catch DIPlib exceptions, add their name and other info to it, then re-throw. To simplify this mechanism and make it easier to future changes, this macro and its partner DIP_END_STACK_TRACE are used by these library functions. Use then as follows:

DIP_START_STACK_TRACE
   // some DIPlib functions that might throw here
DIP_END_STACK_TRACE

This expands to the exact same code as shown under DIP_ADD_STACK_TRACE, but with an additional catch statement that catches std::exception, and throws a dip::RunTimeError with the original exception’s what() string.

When compiling with the CMake configuration flag DIP_ENABLE_STACK_TRACE set to OFF, these macros don’t do anything. Turn the option off if your application would make no use of the stack trace, as building the stack trace does incur some runtime cost.

#define DIP_STACK_TRACE_THIS

Encapsulates a statement in a try/catch block that builds a stack trace when an exception is thrown.

To build a stack trace, some library functions catch DIPlib exceptions, add their name and other info to it, then re-throw. This macro helps by catching and re-throwing exceptions thrown within a single statement:

DIP_STACK_TRACE_THIS( dip::FunctionCall() );

This expands to:

DIP_START_STACK_TRACE
   dip::FunctionCall();
DIP_END_STACK_TRACE

See DIP_START_STACK_TRACE for more information.

#define DIP_PARALLEL_ERROR_DECLARE

Declarations needed before an OpenMP parallel section to catch exceptions.

Exceptions thrown in an OpenMP parallel section cause the program to terminate. They need to be caught within the parallel section, and then rethrown after the parallel section. This and its accompanying macros accomplish this for DIPlib.

A standard parallel section looks like this:

DIP_PARALLEL_ERROR_DECLARE
#pragma omp parallel num_threads( static_cast< int >( nThreads ))
DIP_PARALLEL_ERROR_START
   // Parallel code section
DIP_PARALLEL_ERROR_END

This attempts to preserve the exception types, at least the ones derived from dip::Error. Other exceptions derived from std::exception will be caught and translated to a dip::RunTimeError. Other exception types will not be caught. Note that DIP_PARALLEL_ERROR_END catches exceptions and stores their information, it will not interrupt execution. Only the first exception thrown will be recorded. After the parallel section, DIP_PARALLEL_ERROR_END will throw an exception using the recorded information, if an exception was caught.

DIP_PARALLEL_ERROR_DECLARE declares some variables. It can only be used once within one context, and must be used before the parallel section.