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.
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:
- Using Emacs menu: select an option compile from the menu
Tools. You will see the prompt compile command on the bottom
line of the Emacs window, followed by a suggestion (either make
-k, or the last command used for compilation). Erase the suggestion, and
type in the command that you need, in our case
g++ -g -o test test.cpp
, press return.
- Without Emacs menu: press Esc key together with X (the
same way as you press Control and D to form
Ctrl-D). You will see M-x on the bottom line of the Emacs
window. Type compile and press return, this will give you the
prompt compile
command, followed by a suggestion. As in the first method, erase the
suggestion and type your own command:
g++ -g -o test test.cpp
, then press return.
Note: on some machine you need to press Alt function key instead of
Esc to form the M-x control sequence. This sequence is called
Meta-x.
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:
- Position cursor in the half of the window that you need.
- Choose One window from the File menu or press
Ctrl-X followed by 1.
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.
To start GDB in Emacs, do one of the following:
- Using Emacs menu: select an option debugger from the menu
Tools. On the bottom line of the window you will see a suggestion
gdb. It's a good idea to indicate the name of the executable right
when you are starting debugger (otherwise you'll have to type it every time
you need to re-run your program), so complete the suggestion with the name
of the executable, in our case test.
- Without using Emacs menu: type Esc-x, then after M-x
appears on the bottom line of the window, type gdb, and press
return. Then complete the suggestion gdb by the name of the
executable, in our case test.
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
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).
The following GDB commands allow you to execute a program step-by-step:
- Command s (step) executes one statement of code. If the
current command is a function call, s will go inside the function,
to its first statement.
- Command n (next) executes one line of code. If the
current line is a function call, the entire function is executed.
- Command c (continue) executes the program until the next
breakpoint or until the end if there are no breakpoints.
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.
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:
- Command p (print) followed by a variable name will print
the value of this variable. For instance, command p base will give as
a response something like
$1= 4
. Here 4 is the current value
of the variable base. $1
is the number of the request
to GDB, the next answer would start with $2
, etc.
- Command where gives a sequence of function calls (in reverse
order) to the current point of program execution.
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.
If you have changed the program (say, to correct an error), you need to do
the following:
- Save the file(s) that you have changed.
- Recompile the program (with -g flag) as shown above.
- 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.
- 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.
- 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
.
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.
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.
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.
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.
Type quit at gdb prompt.
Original page created by Elena Machkasova and Jing Zhong.
Modified by Gali Diamant gali@cs.bu.edu, Spring 2003