Introduction
gdb is a an interactive debugger which can be used to debug C programs. While many tools and techniques exist to debug code, gdb can be another tool the programmer can have at their disposal. gdb can be most useful when dealing with Unix's infamous core dumped message.
This tutorial will not cover every aspect of gdb but will instead only focus a few simple uses. Using and understanding gdb best comes through experience and experimentation.
What this article will illustrate is the following:
gdbtest.c
The following program will be used in this article. It represents a very complex way to add 10+10. It contains an error which will cause it to core dump. While the error can be debugged using inspection this article in a later part will use gdb to find the error.
When compiling the program, it is important to add the -g compiler flag. The -g flag will add extra tables to the binary that will make it easier to debug. It is always a good idea to add the -g flag to anything you write and compile.
The only down side is that is makes binaries a lot larger. If a binary was compiled using a -g flag, it can always be made much smaller again by using the Unix utility strip.
1/* gdbtest 2 * by: Todd Burgess (tburgess@netcom.ca) 3 * 4 * gdbtest will be used to illustrate several of the features of gdb 5 * 6 * $Name$ 7 * $Log$ 8 */ 9 #include10 int A (int num) 11 { 12 int n; 13 n = num + 10; 14 return n; 15 } 16 int B () 17 { 18 int *number; 19 *number = NULL; 20 return A(number); 21 } 22 main() 23 { 24 int num; 25 num = B(); 26 printf ("10 + 10 = %d\n",num); 27 }
Running gdbtest Using the Command Line
If you run gdbtest from the command line it should die with the message: Segmentation fault (core dumped). The first strategy which will be demonstrated is running the program inside of gdb to find the error.
Running gdbtest Using gdb
The syntax for running a binary inside of gdb is: gdb binaryname. When first starting gdb this is what is presented:
bushmaster:~/gdb/c$ gdb gdbtest GNU gdb 4.17 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 "i586-slackware-linux"... (gdb)
The (gdb) text at the bottom is the prompt where commands are issued to gdb. In order to access the gdb on-line help facilities type the command help and gdb will guide you through the on-line help.
In order to execute the program the command run is used. run can be followed by command line arguments which will be passed to the program. run will continue to run the program until the program terminates, encounters a break point (more on this later) or receives a signal (like Segmentation Fault).
When the run command is issued, gdb displays the following output (line numbers added for clarity):
1(gdb) run 2Starting program: /home/tburgess/gdb/c/gdbtest 3 Program received signal SIGSEGV, Segmentation fault. 4 0x80485a1 in B () at gdbtest.c:22 5 22 *number = NULL; 6 (gdb)
Line 2 indicates which binary is being executed. Line 3 indicates the program was terminated because of a segmentation fault. Line 4 indicates the error occurred inside the function B(), in the file gdbtest.c at line 22. Line 5 indicates what the contents of this line is. Line 6 is the gdb prompt.
In this case the error is fairly self evident (dereferencing a NULL pointer) but in other cases it may not be so straight forward. The next sections will explain how the state of the program can be examined after it has abnormally terminated.
Viewing the Program Stack
Sometimes it is useful to see see what function calls had been called when the program had abnormally terminated. The where command can be used to see the stack. Viewing the stack is useful when knowing what order the functions were called in is important to debugging.
Using the where command produces the following output (line numbers added for clarity):
1(gdb) where 2#0 0x80485a1 in B () at gdbtest.c:22 3#1 0x80485cb in main () at gdbtest.c:29 4#2 0x80484ee in ___crt_dummy__ () 5(gdb)Line 2 is the current frame (function call) on the stack. The function name, file name where it is and line number are provided. Line 3 is the next item on the stack (the function which called B()).
Navigating the Program Stack
Moving up and down the stack can be done using the up and down commands. Issuing the up command will also show the function name, file name and line number which made the function call. Use of these commands will be illustrated in a later section.
Viewing Variables
Being able to view variables can be useful for determining the state of the program after execution. Viewing the contents of variables is done using the print command (which can be abbreviated to p).
In the following example the variable number is first referenced and then dereferenced:
(gdb) p number $4 = (int *) 0x804856e (gdb) p *number $5 = -1017254775 (gdb)
Navigating the Stack to View Variables
This section illustrates how to combine the previous two sections to print the value of the variable num in main. Simply issuing the command p num will not work. What has to be done is stack frame needs to be moved up one and then the command p num can be executed.
The following example illustrates this:
(gdb) p num No symbol "num" in current context. (gdb) up 1 #1 0x80485cb in main () at gdbtest.c:29 29 num = B(); (gdb) p num $8 = -1073744220 (gdb)
Exiting gdb
To exit gdb use the command: quit.
Summary
The following sections have illustrated some basic but powerful commands which can be used to aid in the analysis of a segmentation fault, These commands can help take the mystery out of the C programmer's most feared error message.
The following section will work well if program has a segmentation fault inside gdb but what about the case where the program has a segmentation fault outside of gdb and all that is left is a core file. The next section will illustrate how gdb can be used to analyze a core file.
Core files
In order to analyze a core file the following syntax is used: gdb -c (name of core file) (name of binary which core dumped. Example: gdb -c core gdbtest.
The following is the output of gdb when it loads the core file:
bushmaster:~/gdb/c$ gdb -c core gdbtest GNU gdb 4.17 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 "i586-slackware-linux"... Core was generated by `gdbtest'. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.5...done. Reading symbols from /lib/ld-linux.so.1...done. #0 0x80485a1 in B () at gdbtest.c:22 22 *number = NULL; (gdb)
gdb shows what line of code caused the program to core dump. All the commands shown in the previous section can be used to examine the state of the program when it core dumped.
Forcing a Core Dump
While frequently core dumps happen when least desired, it is possible to force Unix to terminate the process's execution and write it to a core file. To force a foreground process to core dump hold down the control key and press the \ key.
If the process is a background process it can either be brought to the foreground and killed using the procedure mentioned or killed with signal 11 (ie kill -11 processid).
Conclusions
What has been illustrated only scratches the surface of what is a very powerful utility. For instance, this tutorial makes no mention of how to step through the execution of a program (a very useful exercise). By using some of and expanding on the ideas presented here the programmer can add yet another tool to their programming arsenal.
All the best.
Last updated: March 1, 2000