1 This chapter describes some tips and tricks for debugging numerical
2 programs which use GSL.
6 * Examining floating point registers::
7 * Handling floating point exceptions::
8 * GCC warning options for numerical programs::
9 * Debugging References::
15 @cindex debugging numerical programs
17 Any errors reported by the library are passed to the function
18 @code{gsl_error}. By running your programs under gdb and setting a
19 breakpoint in this function you can automatically catch any library
20 errors. You can add a breakpoint for every session by putting
28 into your @file{.gdbinit} file in the directory where your program is
31 If the breakpoint catches an error then you can use a backtrace
32 (@code{bt}) to see the call-tree, and the arguments which possibly
33 caused the error. By moving up into the calling function you can
34 investigate the values of variables at that point. Here is an example
35 from the program @code{fft/test_trap}, which contains the following
39 status = gsl_fft_complex_wavetable_alloc (0, &complex_wavetable);
43 The function @code{gsl_fft_complex_wavetable_alloc} takes the length of
44 an FFT as its first argument. When this line is executed an error will
45 be generated because the length of an FFT is not allowed to be zero.
47 To debug this problem we start @code{gdb}, using the file
48 @file{.gdbinit} to define a breakpoint in @code{gsl_error},
53 GDB is free software and you are welcome to distribute copies
54 of it under certain conditions; type "show copying" to see
55 the conditions. There is absolutely no warranty for GDB;
56 type "show warranty" for details. GDB 4.16 (i586-debian-linux),
57 Copyright 1996 Free Software Foundation, Inc.
59 Breakpoint 1 at 0x8050b1e: file error.c, line 14.
63 When we run the program this breakpoint catches the error and shows the
68 Starting program: test_trap
70 Breakpoint 1, gsl_error (reason=0x8052b0d
71 "length n must be positive integer",
72 file=0x8052b04 "c_init.c", line=108, gsl_errno=1)
74 14 if (gsl_error_handler)
79 The first argument of @code{gsl_error} is always a string describing the
80 error. Now we can look at the backtrace to see what caused the problem,
84 #0 gsl_error (reason=0x8052b0d
85 "length n must be positive integer",
86 file=0x8052b04 "c_init.c", line=108, gsl_errno=1)
88 #1 0x8049376 in gsl_fft_complex_wavetable_alloc (n=0,
89 wavetable=0xbffff778) at c_init.c:108
90 #2 0x8048a00 in main (argc=1, argv=0xbffff9bc)
92 #3 0x80488be in ___crt_dummy__ ()
97 We can see that the error was generated in the function
98 @code{gsl_fft_complex_wavetable_alloc} when it was called with an
99 argument of @var{n=0}. The original call came from line 94 in the
100 file @file{test_trap.c}.
102 By moving up to the level of the original call we can find the line that
107 #1 0x8049376 in gsl_fft_complex_wavetable_alloc (n=0,
108 wavetable=0xbffff778) at c_init.c:108
109 108 GSL_ERROR ("length n must be positive integer", GSL_EDOM);
111 #2 0x8048a00 in main (argc=1, argv=0xbffff9bc)
113 94 status = gsl_fft_complex_wavetable_alloc (0,
119 Thus we have found the line that caused the problem. From this point we
120 could also print out the values of other variables such as
121 @code{complex_wavetable}.
123 @node Examining floating point registers
124 @section Examining floating point registers
126 The contents of floating point registers can be examined using the
127 command @code{info float} (on supported platforms).
131 st0: 0xc4018b895aa17a945000 Valid Normal -7.838871e+308
132 st1: 0x3ff9ea3f50e4d7275000 Valid Normal 0.0285946
133 st2: 0x3fe790c64ce27dad4800 Valid Normal 6.7415931e-08
134 st3: 0x3ffaa3ef0df6607d7800 Spec Normal 0.0400229
135 st4: 0x3c028000000000000000 Valid Normal 4.4501477e-308
136 st5: 0x3ffef5412c22219d9000 Zero Normal 0.9580257
137 st6: 0x3fff8000000000000000 Valid Normal 1
138 st7: 0xc4028b65a1f6d243c800 Valid Normal -1.566206e+309
139 fctrl: 0x0272 53 bit; NEAR; mask DENOR UNDER LOS;
140 fstat: 0xb9ba flags 0001; top 7; excep DENOR OVERF UNDER LOS
149 Individual registers can be examined using the variables @var{$reg},
150 where @var{reg} is the register name.
154 $1 = 0.02859464454261210347719
157 @node Handling floating point exceptions
158 @section Handling floating point exceptions
160 It is possible to stop the program whenever a @code{SIGFPE} floating
161 point exception occurs. This can be useful for finding the cause of an
162 unexpected infinity or @code{NaN}. The current handler settings can be
163 shown with the command @code{info signal SIGFPE}.
166 (gdb) info signal SIGFPE
167 Signal Stop Print Pass to program Description
168 SIGFPE Yes Yes Yes Arithmetic exception
172 Unless the program uses a signal handler the default setting should be
173 changed so that SIGFPE is not passed to the program, as this would cause
174 it to exit. The command @code{handle SIGFPE stop nopass} prevents this.
177 (gdb) handle SIGFPE stop nopass
178 Signal Stop Print Pass to program Description
179 SIGFPE Yes Yes No Arithmetic exception
183 Depending on the platform it may be necessary to instruct the kernel to
184 generate signals for floating point exceptions. For programs using GSL
185 this can be achieved using the @code{GSL_IEEE_MODE} environment variable
186 in conjunction with the function @code{gsl_ieee_env_setup} as described
187 in @pxref{IEEE floating-point arithmetic}.
190 (gdb) set env GSL_IEEE_MODE=double-precision
194 @node GCC warning options for numerical programs
195 @section GCC warning options for numerical programs
196 @cindex warning options
197 @cindex gcc warning options
199 Writing reliable numerical programs in C requires great care. The
200 following GCC warning options are recommended when compiling numerical
203 @comment Uninitialized variables, conversions to and from integers or from
204 @comment signed to unsigned integers can all cause hard-to-find problems. For
205 @comment many non-numerical programs compiling with @code{gcc}'s warning option
206 @comment @code{-Wall} provides a good check against common errors. However, for
207 @comment numerical programs @code{-Wall} is not enough.
209 @comment If you are unconvinced take a look at this program which contains an
210 @comment error that can occur in numerical code,
213 @comment #include <math.h>
214 @comment #include <stdio.h>
216 @comment double f (int x);
220 @comment double a = 1.5;
221 @comment double y = f(a);
222 @comment printf("a = %g, sqrt(a) = %g\n", a, y);
226 @comment double f(x) @{
227 @comment return sqrt(x);
229 @comment @end example
232 @comment This code compiles cleanly with @code{-Wall} but produces some strange
236 @comment bash$ gcc -Wall tmp.c -lm
237 @comment bash$ ./a.out
238 @comment a = 1.5, sqrt(a) = 1
239 @comment @end example
242 @comment Note that adding @code{-ansi} does not help here, since the program does
243 @comment not contain any invalid constructs. What is happening is that the
244 @comment prototype for the function @code{f(int x)} is not consistent with the
245 @comment function call @code{f(y)}, where @code{y} is a floating point
246 @comment number. This results in the argument being silently converted to an
247 @comment integer. This is valid C, but in a numerical program it also likely to
248 @comment be a programming error so we would like to be warned about it. (If we
249 @comment genuinely wanted to convert @code{y} to an integer then we could use an
250 @comment explicit cast, @code{(int)y}).
252 @comment Fortunately GCC provides many additional warnings which can alert you to
253 @comment problems such as this. You just have to remember to use them. Here is a
254 @comment set of recommended warning options for numerical programs.
257 gcc -ansi -pedantic -Werror -Wall -W
258 -Wmissing-prototypes -Wstrict-prototypes
259 -Wtraditional -Wconversion -Wshadow
260 -Wpointer-arith -Wcast-qual -Wcast-align
261 -Wwrite-strings -Wnested-externs
262 -fshort-enums -fno-common -Dinline= -g -O2
266 For details of each option consult the manual @cite{Using and Porting
267 GCC}. The following table gives a brief explanation of what types of
268 errors these options catch.
271 @item -ansi -pedantic
272 Use ANSI C, and reject any non-ANSI extensions. These flags help in
273 writing portable programs that will compile on other systems.
275 Consider warnings to be errors, so that compilation stops. This prevents
276 warnings from scrolling off the top of the screen and being lost. You
277 won't be able to compile the program until it is completely
280 This turns on a set of warnings for common programming problems. You
281 need @code{-Wall}, but it is not enough on its own.
283 Turn on optimization. The warnings for uninitialized variables in
284 @code{-Wall} rely on the optimizer to analyze the code. If there is no
285 optimization then these warnings aren't generated.
287 This turns on some extra warnings not included in @code{-Wall}, such as
288 missing return values and comparisons between signed and unsigned
290 @item -Wmissing-prototypes -Wstrict-prototypes
291 Warn if there are any missing or inconsistent prototypes. Without
292 prototypes it is harder to detect problems with incorrect arguments.
294 This warns about certain constructs that behave differently in
295 traditional and ANSI C. Whether the traditional or ANSI interpretation
296 is used might be unpredictable on other compilers.
298 The main use of this option is to warn about conversions from signed to
299 unsigned integers. For example, @code{unsigned int x = -1}. If you need
300 to perform such a conversion you can use an explicit cast.
302 This warns whenever a local variable shadows another local variable. If
303 two variables have the same name then it is a potential source of
305 @item -Wpointer-arith -Wcast-qual -Wcast-align
306 These options warn if you try to do pointer arithmetic for types which
307 don't have a size, such as @code{void}, if you remove a @code{const}
308 cast from a pointer, or if you cast a pointer to a type which has a
309 different size, causing an invalid alignment.
310 @item -Wwrite-strings
311 This option gives string constants a @code{const} qualifier so that it
312 will be a compile-time error to attempt to overwrite them.
314 This option makes the type of @code{enum} as short as possible. Normally
315 this makes an @code{enum} different from an @code{int}. Consequently any
316 attempts to assign a pointer-to-int to a pointer-to-enum will generate a
317 cast-alignment warning.
319 This option prevents global variables being simultaneously defined in
320 different object files (you get an error at link time). Such a variable
321 should be defined in one file and referred to in other files with an
322 @code{extern} declaration.
323 @item -Wnested-externs
324 This warns if an @code{extern} declaration is encountered within a
327 The @code{inline} keyword is not part of ANSI C. Thus if you want to use
328 @code{-ansi} with a program which uses inline functions you can use this
329 preprocessor definition to remove the @code{inline} keywords.
331 It always makes sense to put debugging symbols in the executable so that
332 you can debug it using @code{gdb}. The only effect of debugging symbols
333 is to increase the size of the file, and you can use the @code{strip}
334 command to remove them later if necessary.
337 @comment For comparison, this is what happens when the test program above is
338 @comment compiled with these options.
341 @comment bash$ gcc -ansi -pedantic -Werror -W -Wall -Wtraditional
342 @comment -Wconversion -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align
343 @comment -Wwrite-strings -Waggregate-return -Wstrict-prototypes -fshort-enums
344 @comment -fno-common -Wmissing-prototypes -Wnested-externs -Dinline=
345 @comment -g -O4 tmp.c
346 @comment cc1: warnings being treated as errors
347 @comment tmp.c:7: warning: function declaration isn't a prototype
348 @comment tmp.c: In function `main':
349 @comment tmp.c:9: warning: passing arg 1 of `f' as integer rather than floating
350 @comment due to prototype
351 @comment tmp.c: In function `f':
352 @comment tmp.c:14: warning: type of `x' defaults to `int'
353 @comment tmp.c:15: warning: passing arg 1 of `sqrt' as floating rather than integer
354 @comment due to prototype
355 @comment make: *** [tmp] Error 1
356 @comment @end example
359 @comment The error in the prototype is flagged, plus the fact that we should have
360 @comment defined main as @code{int main (void)} in ANSI C. Clearly there is some
361 @comment work to do before this program is ready to run.
363 @node Debugging References
364 @section References and Further Reading
366 The following books are essential reading for anyone writing and
367 debugging numerical programs with @sc{gcc} and @sc{gdb}.
371 R.M. Stallman, @cite{Using and Porting GNU CC}, Free Software
372 Foundation, ISBN 1882114388
375 R.M. Stallman, R.H. Pesch, @cite{Debugging with GDB: The GNU
376 Source-Level Debugger}, Free Software Foundation, ISBN 1882114779
380 For a tutorial introduction to the GNU C Compiler and related programs,
385 B.J. Gough, @cite{An Introduction to GCC}, Network Theory Ltd, ISBN