gdb
debuggerTo improve our debugging skills. The better we can debug, the faster we can program and the less frustration we experience along the way.
One means of debugging is to use print statements. Some argue that using a debugger is more convenient. For example [2b]:
A debugger is a program that runs other programs, allowing its user to exercise some degree of control over these programs, and to examine them when things go amiss [1a].
In particular, debuggers let you [3]:
When you compile, include a -g
flag. Following that,
you can execute gdb
on the executable created.
For example:
Shell> g++ -g hello.c -o myprog Shell> gdb myprog
gdb
commandsThe following table is based on [1b]. It should be
noted that although gdb
supports a wide variety of
commands, learning only a few can go a long way to help with debugging.
Essential Commands | |
run command-line-arguments |
|
kill | the kill command terminates the currently running program so you can start debugging at the beginning. (You can also just re-type run and it will prompt to start again from the begining) |
where | produce a backtrace -- the chain of function calls that brought the program to its current place. The commands bt and backtrace are synonyms |
quit | quit the debugger |
help | list help topics |
help command | describe command |
Listing Source Code | |
list | show the next ten lines of source code |
list - | show previous ten lines |
list [file:]num | show the source surrounding line number num |
list [file:]function | show the source surrounding the beginning of the function |
list f,l | show the source from line f to line l |
Breakpoints | |
break [file:]num | set breakpoint at line number [in file] |
break [file:]function | set breakpoint at start of function [in file] |
delete [num] | delete the breakpoint numbered num |
continue [count] | Used to restart execution of the program after a breakpoint. If count is specified, ignore this breakpoint next count times |
disable [num] | disables the breakpoint numbered num. If no argument is used, all breakpoints are disabled |
enable [num] | enabbles the breakpoint numbered num. If no argument is used, all breakpoints are enabled |
info breakpoints | print out all of your current breakpoints |
Execution Control | |
step [count] |
|
next [count] | Like step, except that
function calls are treated different:
|
finish | Keeps doing nexts, without stopping, until reaching the end of the current function |
Displaying Variables | |
print [expr] |
|
display expr | show the value of expr each time the program stops |
undisplay num | remove number(s) num from list of automatically displayed expressions |
info display | show numbered list of all automatic display expressions |
gdb
sessionThe following is an example session, recorded using the script
command:
justin@cab104:~/gdbPlaying>cat sample.c #include <stdio.h> void printArgs(int argc, char *argv[]); void processSomething(void); /*-------------------------------------------------- */ int main(int argc, char *argv[]) { printArgs(argc, argv); processSomething(); return(0); } /*-------------------------------------------------- * Purpose: Echo all command-line arguments to standard output * Credit: Funcation taken from Stevens p.166 (Program 7.2) */ void printArgs(int argc, char *argv[]) { int i; for (i = 0; i < argc; i++) /* echo all command-line args */ printf("argv[%d]: %s\n", i, argv[i]); } /*-------------------------------------------------- */ void processSomething(void) { char *buf; sprintf(buf, "I wuz here\n"); /* make string */ printf("processSomething: %s\n", buf); /* display string */ }
I used the cat
command to introduce the program file
we will work with.
justin@cab104:~/gdbPlaying>g++ -g sample.c justin@cab104:~/gdbPlaying>./a.out argv[0]: ./a.out Segmentation fault (core dumped)
Ok, this executable has a bug somethere. We invoke gdb
to
help us find it..
justin@cab104:~/gdbPlaying>gdb a.out GNU gdb 4.18 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "sparc-sun-solaris2.7"...
The above is the introductory message that gdb
gives us.
First off, we try running the program with some arguments
(gdb) run I am using 5 arguments Starting program: /usr/ohaton1/grad/justin/gdbPlaying/a.out I am using 5 arguments argv[0]: /usr/ohaton1/grad/justin/gdbPlaying/a.out argv[1]: I argv[2]: am argv[3]: using argv[4]: 5 argv[5]: arguments Program received signal SIGSEGV, Segmentation fault. 0xff2706d0 in memcpy () from /usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1
Now we want to pinpoint where the segmentation fault occurred, so
we use the where
command
(gdb) where #0 0xff2706d0 in memcpy () from /usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1 #1 0xff2fe394 in _doprnt () from /usr/lib/libc.so.1 #2 0xff3018d4 in sprintf () from /usr/lib/libc.so.1 #3 0x10a90 in processSomething__Fv () at sample.c:33 #4 0x109d4 in main (argc=6, argv=0xffbefbac) at sample.c:11
Aha! main
called processSomething
which
called sprintf
and then died somewhere thereafter.
Lets take a look at the function processSomething
..
(gdb) list processSomething 25 } 26 27 /*-------------------------------------------------- 28 */ 29 void processSomething(void) 30 { 31 char *buf; 32 33 sprintf(buf, "I wuz here\n"); /* make string */ 34 printf("processSomething: %s\n", buf); /* display string */
Ok, now the problem is more evident. We are trying to write to a
string buf
that has not yet been allocated any memory space.
In a separate window we invoke our favorite editor. We replace
char *buf;
with char buf[80];
. In a
separate window again we compile our program again. Note that we don't
have to leave gdb
during this time. Now that our fix is
done, we verify that it solves the problem..
(gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) y `/usr/ohaton1/grad/justin/gdbPlaying/a.out' has changed; re-reading symbols. Starting program: /usr/ohaton1/grad/justin/gdbPlaying/a.out I am using 5 arguments argv[0]: /usr/ohaton1/grad/justin/gdbPlaying/a.out argv[1]: I argv[2]: am argv[3]: using argv[4]: 5 argv[5]: arguments processSomething: I wuz here Program exited normally. (gdb) quit
Alright. Mission accomplished. That wasn't so bad, eh?