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