Operating Systems - Projects and Exercises

C Programming Debugging Guide (GNU gdb)

Contents

The left arrow above will return you to the Home page
The left arrows below will return you to the Previous page

Go back top

Basic Debugging

If your program compiles, but doesn't work, you should compile it with the -Wall argument using gcc...i.e.

gcc -Wall test.c

This turns on all the compiler warnings, and, with any luck, may be enough to show you where you are going wrong. Make sure you fix every warning displayed, or at least understand why the warning is acceptable. In fact it is advisable to always compile your programs with the -Wall option to catch dubious programming practices.

If this doesn't turn on any lightbulbs, you can try in-program debugging by inserting printf statements through the code so that key information gets displayed as the program runs. To ensure that output actually gets displayed before a subsequent core dump, write your output to stderr which has unbufferred output. Also you may wish to use conditional compilation to turn this display on and off. e.g.

#define DEBUG
 ...
#ifdef DEBUG
    fprintf(stderr,"Current command line buffer: %s\n", buffer);

#endif

Instead of #defineing DEBUG in your code, you can define it in the gcc command line:

gcc -Wall -D DEBUG source.c -o program
Alternatively (or if you are still stuck) you can try using a debugger. A debugger allows you to "look inside" your program interactively as it runs. The debugger used with gcc on UNIX platforms is gdb - the GNU debugger. To use the debugger you must compile your code with the -g flag. i.e.
gcc -g -Wall test.c

gdb allows you to abbreviate commands (that is you only have to type p for print, b for break etc)

Go back top

Starting the Debugger

gdb a.out
b main
run

This runs the debugger on the executable a.out, sets a breakpoint at main and then starts the program executing. The program will stop at the start of your main program. You can now step through the program, examine the values of variables, set other breakpoints, etc

If you know which function is going wrong you can specify that function, rather than main as the first breakpoint at which to stop.

Go back top

Debugger Commands

run [command line arguments]
this sets the program running. It will run as normal until it hits a breakpoint or your program finishes (or crashes). You can put any normal command line arguments you would use with your program after the run command.
step
steps into the code - executes the next instruction; will step into a function.
next
steps over the code - stops at the next intruction in the current scope; i.e. function calls that appear within the line of code are executed without stopping.
cont
allows the program to continue running. It will run as normal until it hits a breakpoint or your program finishes (or crashes).
print
prints the value of a variable. The following all work:
p i
prints the value of the variable i
p (i + 1)
prints the value of the variable i + 1 (i stays the same)
p *a
prints the value stored in the memory who's address is stored in a
list
lists your source code. You can say:
l 23
list code around line 23
l io.c:23
list code around line 23 of the file io.c
l foo
list code around the beginning of function foo
l io.c:foo
list code around the beginning of function foo in the file io.c
break
sets a breakpoint. You can say:
b 23
set a break point at line 23
b foo
set a break point at the function foo
delete
removes a specified breakpoint. You say:
d 1
removes breakpoint 1 - when you set a breakpoint the debugger tells you the breakpoint number or you can discover all current breakpoints using info break
clear
clear a breakpoint at specified line or function (see break above)
info break
lists all the break points you have set
watch <expression>
Set a watchpoint for an expression. A watchpoint stops execution of your program whenever the value of an expression changes:
watch timer
will stop the program whenever (and wherever) the variable timer is changed.
bt
prints a back trace, that is shows you which functions were called to get the program to the state it is now in. If you say bt full you also get the value of each function’s variables. You can also use the bt command to display the execution stack if a core dump/segmentatoion error occurs while you are running a program in the debugger.
set variable i = 3
sets the variable i to the value 3.
help
read the online help
quit
quit the debugger (and your program)
Go back top

Core Dumps

If your program core dumps you can use the debugger to see what went wrong. Use the command:

gdb a.out core

where a.out is a copy of your program compiled with -g and core is the core file. You can then use bt to see what routine you were in and from where it was called when the core dump occurred.

You can also use the bt command to display the execution stack if a core dump/segmentatoion error occurs while you are running a program in the debugger.

Go back top

Conclusion

There is much, much more you can do with the debugger that isn’t covered here. There are also graphical interfaces to the debugger.

Go back top

Further References

Go back top

For use only by students and instructors using the supplementary material available with the text book: "Operating Systems - Internals and Design Principles", William Stallings, Prentice Hall, 5th Edition, 2004. Not to be printed out or copied by any other persons or used for any other purpose without written permission of the author(s).

©