Using gdb


This lab covers the following material:

General Information on GDB

The goal of this lab is to learn how to use gdb under the UNIX programming environment (in particular, in conjunction with the text editor Emacs). Many professional programmers as well as students find debuggers extremely helpful for finding errors in their programs. Using a debugger may save you hours of work, because by using a debugger you can learn exactly what your program is doing (i.e. execute your program step-by-step, examine values of variables and sequences of function calls, and so on), which allows you to pinpoint and correct an error. We do not insist that you use a debugger, but it is our experience that using it makes debugging a program (especially a long one) much easier.

You can use GDB tutorial to get familiar with basic GDB commands and capabilities. You may also want to keep a copy of the GDB quick reference card handy while using gdb. A copy of the reference card will be given in class.

Assignment for this Lab

In this lab you will practice using the debugger to find run-time errors in a program. We will use two examples: a simple program that uses a recursive function to compute a power of an integer number, and a program that uses classes and dynamic memory allocation. The second example illustrates how to use debugger in the presence of separate compilation and how to print out values of objects and pointers.

The lab shows how to use GDB in the text editor Emacs. There are many advantages in using GDB in Emacs. In particular, Emacs shows the program as you are stepping through it with GDB, indicating which line you are on.
We also mention how to use GDB without Emacs. You might need it if you are connected to csa via telnet and are not able to run Emacs in a separate window.

The lab contains several questions that you need to answer as you are doing the exercises. In the end of the lab please submit the answers (hand-written, you don't need to submit any code).

Part 1: compiling for GDB; using basic GDB commands

Please download the file test.cpp.

View the program using Emacs. Read the program to understand what it is supposed to do. Compile it and run it on some data, say base 3 and exponent 4. What happens? Try to run it again with some other data. Now look at the program code. Do you see the error right away? Even if you do, proceed with the rest of the assignment, do not change the program in any way.

Compiling for GDB (with and without Emacs)

Important: to compile a program for running under debugger, you must use -g flag in compilation. The flag indicates to the compiler that it needs to store information about the code, s.a. line numbers, variable names, etc., that otherwise would be thrown away during compilation. Without this information you can not use the debugger.
Example: to compile a file test.cpp, type
	g++ -g -o test test.cpp 
(this will produce an executable named test).

The example above shows how to compile a program from the UNIX command line (i.e. in the terminal window). Using Emacs, you can compile a program as follows:

In both cases of compiling in Emacs after the compilation command is entered, the Emacs window splits into two windows, one with your program, and the other with the compilation results. In the compilation window you should get the message Compilation finished indicating that the program has compiled correctly.

If the window is split into two, you can restore it to be one window as follows:

Note that you can compile a program in Emacs even if you are not using GDB (in this case you don't need -g flag).

Step 1. Compile the program test.cpp in Emacs using one of the methods above.

Starting GDB (with and without Emacs)

To start GDB in Emacs, do one of the following: The GDB program will start in the Emacs window. After the copyright and other information about GDB, you'll see the prompt (gdb).

Step 2. Start GDB using one of the methods above.

To run GDB in the UNIX (i.e. terminal) window, type gdb at command line. You may also supply the name of the executable, for instance gdb test.

Running GDB

Setting breakpoints.

If you type a command run, the executable starts running. Before you do it, you need to set up breakpoints to indicate where the program should stop so that you execute it step-by-step. If no breakpoints is set, the program will run to completion.

You can set breakpoints by specifying a line number or a function name. In this lab we will use line numbers to set breakpoints.

Step 3. Type b 25 at the GDB prompt to set a breakpoint on line 25.

Step 4. Type run to run the program. Enter the base and the exponent when the program prompts you to do so. Remember the base and the exponent that you have entered (you'll need to submit them as a part of your answer). The program should stop at the breakpoint and display the program code in the other half of the window with the arrow pointing to the line 25 (current execution point).

Stepping through a program

The following GDB commands allow you to execute a program step-by-step: When to use s and when n: if the current line is your own function (or a method) that you need to examine, use s. If it is a standard C++ function, s.a. cout or cin, or it is your own function that you are not interested in at the moment, use n.

Note: if you have typed s on a standard C++ function, s.a. cout, GDB will bring up the code for this function. To return to your own code, type finish, this will execute the standard function until the end and bring you to the next command in your code. One cout or cin line may contain several commands, so if finish brings you to the same line of your code, use command n next.

Printing data

When you are walking through a program, you may examine values of variables, the sequence of function calls, etc. Here are some very basic commands that you can use:

Interrupting execution of a program

Command kill interrupts execution of the program running under GDB.

Step 5. Type s to execute the next statement of your program. Look at the position of the arrow in the program window. Type where to see the sequence of function calls: it should include main and the call to the function power.

Question 1. Type commands p base and p exponent to display the values of the base and the exponent. What responses do you get for each of the commands?

Step 6. Continue executing the program step-by-step by repeating command s. Use command where to display the sequence of function calls.

Question 2. What is the sequence of function calls after you repeat command s 5 times?

Step 7. Continue testing the program until you figure out the error. If you want the program to run all the way to the end without stopping, type c. If you want to restart the program after it has finished running, type run. If you want to add more breakpoints, use command b. Use other GDB commands if needed (see above, also see the GDB tutorial).

Question 3. What is the error in the program? What happens when the program runs with this error? Justify your answer by information that you got when running the debugger.

Changing the program and recompiling

If you have changed the program (say, to correct an error), you need to do the following:
  1. Save the file(s) that you have changed.
  2. Recompile the program (with -g flag) as shown above.
  3. If your GDB session is still running, then choosing Debugger from the Emacs menu or typing Esc-x gdb will bring you back to the current session. Or choose gud followed by the name of the executable from the Buffer menu to get back the GDB session.
  4. You need to restart the program by typing run (you may need to kill the program currently running). GDB will automatically use the new version of the program.
  5. If the line numbers have changed you may need to reset breakpoints. Use command info break to see current breakpoints. Use command d (delete) followed by the number of a breakpoint to delete the breakpoint.

Step 8. Correct the error. Recompile the program (see above). You don't need to restart the debugger.

Question 4. How many function calls does the program make before the recursive function starts returning? (Count main as the first call). Make sure to specify the data that you have entered.

Part 2. Using GDB with Separate Compilation; Objects and Pointers

Please download the above files .

If you haven't done so already, please download the files Point23.h, Point23.cpp, main.cpp, and Makefile.

Separate Compilation

You can type commands for separate compilation of files one-by-one after the compile prompt on the bottom line of the Emacs window (see above). If you do it this way, make sure to use -g flag for compilation of every .cpp file.
However, it is more convenient to use Makefile for separate compilation. Note that in the Makefile given for this lab the compilation flags are specified only once, on the line
CXXFLAGS = -Wall -g
These flags are used for compilation of all files.
If you are given a Makefile where -g flag is not used, you have to add it yourself.

To compile a program in Emacs using Makefile, select compile from the menu (or type Esc-x compile) and choose make as a compilation command.

Setting breakpoints in multiple files

If you are working with more than one file, you need to precede the line number of a breakpoint with the file name, for instance:
b main.cpp:25 sets a breakpoint on line 25 of file main.cpp.

It is also convenient to set breakpoints at a particular function, for instance:
b main sets a breakpoint at the beginning of the function main(),
b Point23::get_x sets a breakpoint at the beginning of the method get_x of the class Point23. Note that the class name is required.
Since all functions in your program have different names, you don't need to specify the file name when setting a breakpoint at a function.

Printing values of objects, pointers, etc.

Command p allows you to print a value of any expression. For instance, if p1 is a object of class Point23, command p p1 prints out the static part of the object (but not the dynamically allocated part). If Ptr is a pointer then p *Ptr prints its content, if datPtr is a name of an array then p datPtr[0] prints its first element.

Question 5. Run the program under GDB, understand its behavior. Explain what goes wrong in the program (i.e. why the coordinates of the second point have changed when we have changed coordinates of the first one). Justify your answer by the data from the debugger.

Bonus Question . Without writing code, explain how to fix the problem.

Note: you don't need to fix the error in this assignment, only to explain it.

Redirection of Input

This material is not required for the lab, but it is helpful if you are debugging a program that takes input, especially if the input is long.

Redirecting of input means that your program gets data from a file, i.e. you don't need to type the data every time you run a program, you can just store it in a file once.

Suppose test is the name of the executable, and the data is stored in a file data. If you are running the program without a debugger, type

test < data
This will make the program read all input data from the file data.
If you are running a program in debugger, type
run < data
instead of just run.

To practice, try running the executable test from the first part of the lab on the data file data with and without gdb.

Quitting GDB

Type quit at gdb prompt.



Original page created by Elena Machkasova and Jing Zhong.
Modified by Gali Diamant gali@cs.bu.edu, Spring 2003