Go to the first, previous, next, last section, table of contents.
This chapter describes the way that GSL functions report and handle errors. By examining the status information returned by every function you can determine whether it succeeded or failed, and if it failed you can find out what the precise cause of failure was. You can also define your own error handling functions to modify the default behavior of the library.
The functions described in this section are declared in the header file `gsl_errno.h'.
The library follows the thread-safe error reporting conventions of the
POSIX Threads library. Functions return a non-zero error code to
indicate an error and 0
to indicate success.
int status = gsl_function(...) if (status) { /* an error occurred */ ..... /* status value specifies the type of error */ }
The routines report an error whenever they cannot perform the task requested of them. For example, a root-finding function would return a non-zero error code if could not converge to the requested accuracy, or exceeded a limit on the number of iterations. Situations like this are a normal occurrence when using any mathematical library and you should check the return status of the functions that you call.
Whenever a routine reports an error the return value specifies the type
of error. The return value is analogous to the value of the variable
errno
in the C library. The caller can examine the return code
and decide what action to take, including ignoring the error if it is
not considered serious.
In addition to reporting errors the library also has an error handler function. The error handler is called by library functions when they report an error, just before they return to the caller. The purpose of the handler is to provide a function where a breakpoint can be set that will catch library errors when running under the debugger. It is not intended for use in production programs, which should handle any errors using the return codes.
The error code numbers returned by library functions are defined in the
file `gsl_errno.h'. They all have the prefix GSL_
and
expand to non-zero constant integer values. Many of the error codes use
the same base name as a corresponding error code in C library. Here are
some of the most common error codes,
malloc
.
The error codes can be converted into an error message using the
function gsl_strerror
.
printf("error: %s\n", gsl_strerror (status));
would print an error message like error: output range error
for a
status value of GSL_ERANGE
.
The default behavior of the GSL error handler is to print a short
message and call abort()
. When the default is in use programs
will stop with a core-dump whenever a library routine reports an error.
This is intended as a fail-safe default for programs which do not check
the return status of library routines (we don't encourage you to write
programs this way).
If you turn off the default error handler it is your responsibility to check the return values of routines and handle them yourself. You can also customize the error behavior by providing a new error handler. For example, an alternative error handler could log all errors to a file, ignore certain error conditions (such as underflows), or start the debugger and attach it to the current process when an error occurs.
All GSL error handlers have the type gsl_error_handler_t
, which is
defined in `gsl_errno.h',
This is the type of GSL error handler functions. An error handler will
be passed four arguments which specify the reason for the error (a
string), the name of the source file in which it occurred (also a
string), the line number in that file (an integer) and the error number
(an integer). The source file and line number are set at compile time
using the __FILE__
and __LINE__
directives in the
preprocessor. An error handler function returns type void
.
Error handler functions should be defined like this,
void handler (const char * reason, const char * file, int line, int gsl_errno)
To request the use of your own error handler you need to call the
function gsl_set_error_handler
which is also declared in
`gsl_errno.h',
This functions sets a new error handler, new_handler, for the GSL library routines. The previous handler is returned (so that you can restore it later). Note that the pointer to a user defined error handler function is stored in a static variable, so there can be only one error handler per program. This function should be not be used in multi-threaded programs except to set up a program-wide error handler from a master thread. The following example shows how to set and restore a new error handler,
/* save original handler, install new handler */ old_handler = gsl_set_error_handler (&my_handler); /* code uses new handler */ ..... /* restore original handler */ gsl_set_error_handler (old_handler);
To use the default behavior (abort
on error) set the error
handler to NULL
,
old_handler = gsl_set_error_handler (NULL);
The error behavior can be changed for specific applications by
recompiling the library with a customized definition of the
GSL_ERROR
macro in the file `gsl_errno.h'.
If you are writing numerical functions in a program which also uses GSL code you may find it convenient to adopt the same error reporting conventions as in the library.
To report an error you need to call the function gsl_error
with a
string describing the error and then return an appropriate error code
from gsl_errno.h
, or a special value, such as NaN
. For
convenience the file `gsl_errno.h' defines two macros which carry
out these steps:
This macro reports an error using the GSL conventions and returns a
status value of gsl_errno
. It expands to the following code fragment,
gsl_error (reason, __FILE__, __LINE__, gsl_errno); return gsl_errno;
The macro definition in `gsl_errno.h' actually wraps the code
in a do { ... } while (0)
block to prevent possible
parsing problems.
Here is an example of how the macro could be used to report that a
routine did not achieve a requested tolerance. To report the error the
routine needs to return the error code GSL_ETOL
.
if (residual > tolerance) { GSL_ERROR("residual exceeds tolerance", GSL_ETOL); }
This macro is the same as GSL_ERROR
but returns a user-defined
status value of value instead of an error code. It can be used for
mathematical functions that return a floating point value.
The following example shows how to return a NaN
at a mathematical
singularity using the GSL_ERROR_VAL
macro,
if (x == 0) { GSL_ERROR_VAL("argument lies on singularity", GSL_ERANGE, GSL_NAN); }
Here is an example of some code which checks the return value of a function where an error might be reported,
#include <stdio.h> #include <gsl/gsl_errno.h> #include <gsl/gsl_fft_complex.h> int main (void) { int status; gsl_set_error_handler_off(); status = gsl_fft_complex_radix2_forward (data, n); if (status) { if (status == GSL_EINVAL) { fprintf (stderr, "invalid argument, n=%d\n", n); } else { fprintf (stderr, "failed, gsl_errno=%d\n", status); } exit (-1); } exit (0); }
The function gsl_fft_complex_radix2
only accepts integer lengths
which are a power of two. If the variable n
is not a power of
two then the call to the library function will return GSL_EINVAL
,
indicating that the length argument is invalid. The function call to
gsl_set_error_handler_off()
stops the default error handler from
aborting the program. The else
clause catches any other possible
errors.
Go to the first, previous, next, last section, table of contents.