Scientific Programming in C IX. Debugging Susi Lehtola 13 November 2012
Debugging Quite often you spend an hour to write a code, and then two hours debugging why it doesn t work properly. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 2/24
Debugging Quite often you spend an hour to write a code, and then two hours debugging why it doesn t work properly. Worst case scenario: spend many weeks finding a trivial bug, e.g., in the unit conversions. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 3/24
Debugging Quite often you spend an hour to write a code, and then two hours debugging why it doesn t work properly. Worst case scenario: spend many weeks finding a trivial bug, e.g., in the unit conversions. Break your problem into simple pieces and test them separately. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 4/24
Debugging, cont d You can always use manual debugging to figure out what goes out in the program, i.e. insert lots of printf statements. Another option is to use debugging tools such as gdb and valgrind. To use the debugging tools you need to use the -g flag when compiling. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 5/24
Debugging, cont d Perhaps the most common problem a beginning C programmer encounters is $. / a. out Segmentation f a u l t ( c o r e dumped ) In these cases you often just want to know where the segfault happens. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 6/24
Example program #i n c l u d e <s t d i o. h> i n t main ( v o i d ) { c o n s t i n t N=100; i n t a r r [N ] ; i n t i ; c o n s t i n t l =7; p r i n t f ( l=%i. \ n, l ) ; / E r r o r i s h e r e upper l i m i t s h o u l d be N, not 2 N / f o r ( i =0; i <2 N; i ++) a r r [ i ]= i ; p r i n t f ( l=%i. \ n, l ) ; } r e t u r n 0 ; Scientific Programming in C, fall 2012 Susi Lehtola Debugging 7/24
Using GDB Let s use the GNU Debugger gdb to see what happens in the program when it is run. $ gcc g s e g f a u l t. c $ gdb. / a. out GNU gdb (GDB) Fedora ( 7. 4. 50.20120120 52. f c 1 7 ) Copyright (C) 2012 Free Software Foundation, Inc. L i c e n s e GPLv3+: GNU GPL v e r s i o n 3 o r l a t e r <h t t p : / / gnu. org / l i c e n s e s / g p l. html> This i s f r e e s o f t w a r e : you a r e f r e e to change and r e d i s t r i b u t e i t. There i s NO WARRANTY, to the extent permitted by law. Type show copying and show w a r r a n t y f o r d e t a i l s. This GDB was configured as x86 64 redhat linux gnu. For bug r e p o r t i n g i n s t r u c t i o n s, p l e a s e s e e : <http : / /www. gnu. org / software /gdb/ bugs / >... Reading symbols from /tmp/a. out... done. ( gdb ) r S t a r t i n g program : /tmp/a. out l =7. Program r e c e i v e d s i g n a l SIGSEGV, Segmentation f a u l t. 0 x0000000000400574 i n main ( ) a t s e g f a u l t. c : 1 2 12 a r r [ i ]= i ; ( gdb ) Scientific Programming in C, fall 2012 Susi Lehtola Debugging 8/24
Here GDB tells you straight away where the problem lies, i.e., at line 9 of segfault.c. You can also check what the value of i is when the assignment failed ( gdb ) d i s p i 1 : i = 111 As you can see, this is significantly larger than the size of the array. Buffer overruns aren t always detected by gdb. Changing the upper limit from 2N to 111 the code works seemingly normally. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 9/24
... but as a result you are touching memory that you re not supposed to touch. As the result, the values of variables that haven t been touched in the code change. $. / a. out l =7. l =109. From this you see that the constant integer is placed in the memory location arr+109. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 10/24
It is often useful to monitor how variables change during the runtime of the code. First, let s set a breakpoint from where we want to start monitoring what happens. ( gdb ) b r e a k 10 B r e a k p o i n t 1 a t 0 x40054a : f i l e s e g f a u l t. c, l i n e 1 0. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 11/24
It is often useful to monitor how variables change during the runtime of the code. First, let s set a breakpoint from where we want to start monitoring what happens. ( gdb ) b r e a k 10 B r e a k p o i n t 1 a t 0 x40054a : f i l e s e g f a u l t. c, l i n e 1 0. If you have multiple translation units linked into the same program, you can define the unit with, e.g. ( gdb ) b r e a k s e g f a u l t. c : 1 0 B r e a k p o i n t 1 a t 0 x40054a : f i l e s e g f a u l t. c, l i n e 1 0. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 12/24
Now we run the code with r for run. ( gdb ) r S t a r t i n g program : /tmp/a. out l =7. B r e a k p o i n t 1, main ( ) a t s e g f a u l t. c : 1 0 10 f o r ( i =0; i <111; i ++) { The execution of the program has halted at line 10. Let s look at how i and l change. Turn on the display of i and l with ( gdb ) d i s p i 1 : i = 0 ( gdb ) d i s p l 2 : l = 7 Scientific Programming in C, fall 2012 Susi Lehtola Debugging 13/24
and continue the execution onto the next line. ( gdb ) n e x t 11 a r r [ i ]= i ; 2 : l = 7 1 : i = 0 ( gdb ) 10 f o r ( i =0; i <111; i ++) { 2 : l = 7 1 : i = 0 ( gdb ) 11 a r r [ i ]= i ; 2 : l = 7 1 : i = 1 ( gdb ) 10 f o r ( i =0; i <111; i ++) { 2 : l = 7 1 : i = 1 ( gdb ) 11 a r r [ i ]= i ; 2 : l = 7 1 : i = 2 ( gdb ) Scientific Programming in C, fall 2012 Susi Lehtola Debugging 14/24
Hitting ENTER will just repeat the same command as seen above. From the output you see how the program runs. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 15/24
Hitting ENTER will just repeat the same command as seen above. From the output you see how the program runs. When the program enters the loop i=0 and l=7 and it has been checked that i<111. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 16/24
Hitting ENTER will just repeat the same command as seen above. From the output you see how the program runs. When the program enters the loop i=0 and l=7 and it has been checked that i<111. Next, arr[0] is set to 0. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 17/24
Hitting ENTER will just repeat the same command as seen above. From the output you see how the program runs. When the program enters the loop i=0 and l=7 and it has been checked that i<111. Next, arr[0] is set to 0. The for loop has been completed, i is incremented and it is once again checked that i<111. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 18/24
Hitting ENTER will just repeat the same command as seen above. From the output you see how the program runs. When the program enters the loop i=0 and l=7 and it has been checked that i<111. Next, arr[0] is set to 0. The for loop has been completed, i is incremented and it is once again checked that i<111. arr[1] is set to 1. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 19/24
Hitting ENTER will just repeat the same command as seen above. From the output you see how the program runs. When the program enters the loop i=0 and l=7 and it has been checked that i<111. Next, arr[0] is set to 0. The for loop has been completed, i is incremented and it is once again checked that i<111. arr[1] is set to 1. i is incremented and checked that i<111. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 20/24
Hitting ENTER will just repeat the same command as seen above. From the output you see how the program runs. When the program enters the loop i=0 and l=7 and it has been checked that i<111. Next, arr[0] is set to 0. The for loop has been completed, i is incremented and it is once again checked that i<111. arr[1] is set to 1. i is incremented and checked that i<111. arr[2] is set to 2. Scientific Programming in C, fall 2012 Susi Lehtola Debugging 21/24
The next command skips over any function calls; if you want to follow into them use the step command instead. The continue command continues running until the next breakpoint is encountered. ( gdb ) c C o n t i n u i n g. l =109. [ I n f e r i o r 1 ( p r o c e s s 12499) e x i t e d n o r m a l l y ] Scientific Programming in C, fall 2012 Susi Lehtola Debugging 22/24
Valgrind The use of the debugger doesn t tell you if you have errors in the memory management. These you can find with memory debuggers such as Valgrind. It is especially useful with dynamic memory allocation, as it also checks for leaked memory (memory that is malloc d but not free d). Scientific Programming in C, fall 2012 Susi Lehtola Debugging 23/24
Valgrind, cont d $ v a l g r i n d. / a. out ==13294== Memcheck, a memory e r r o r detector ==13294== Copyright (C) 2002 2011, and GNU GPL d, by J u l i a n Seward et a l. ==13294== Using Valgrind 3.7.0 and LibVEX ; rerun with h f o r copyright i n f o ==13294== Command :. / a. out ==13294== l =7. ==13294== I n v a l i d w r i t e o f s i z e 4 ==13294== a t 0 x400574 : main ( s e g f a u l t. c : 1 1 ) ==13294== A d d r e s s 0 x70000022a i s not s t a c k d, malloc d o r ( r e c e n t l y ) f r e e d ==13294== ==13294== ==13294== P r o c e s s t e r m i n a t i n g w i t h d e f a u l t a c t i o n o f s i g n a l 11 ( SIGSEGV ) ==13294== A c c e s s not w i t h i n mapped r e g i o n a t a d d r e s s 0 x70000022a ==13294== a t 0 x400574 : main ( s e g f a u l t. c : 1 2 ) ==13294== I f you b e l i e v e t h i s happened as a r e s u l t o f a s t a c k ==13294== overflow in your program s main thread ( u n l i k e l y but ==13294== p o s s i b l e ), you can t r y to i n c r e a s e t h e s i z e o f t h e ==13294== main t h r e a d s t a c k u s i n g t h e main s t a c k s i z e= f l a g. ==13294== The main thread stack s i z e used in t h i s run was 8388608. ==13294== ==13294== HEAP SUMMARY: ==13294== in use at e x i t : 0 bytes in 0 blocks ==13294== t o t a l heap usage : 0 a l l o c s, 0 f r e e s, 0 b y t e s a l l o c a t e d ==13294== ==13294== A l l heap b l o c k s were f r e e d no l e a k s a r e p o s s i b l e ==13294== ==13294== For counts of de t ec t ed and s u p p r e s s e d e r r o r s, rerun with : v ==13294== ERROR SUMMARY: 1 e r r o r s from 1 contexts ( suppressed : 2 from 2) Segmentation f a u l t ( c o r e dumped ) Scientific Programming in C, fall 2012 Susi Lehtola Debugging 24/24