{={copyright-marge}{1}}
{={pdf}{debugging-lab}}
Summary: We explore the use of DDD, one of the standard
debugging systems.
Prerequisites:
Understanding of basic C control structures. Understanding of Linux.
a. Create a new directory for this lab. I would suggest
CSC161/Labs/Debugging, but it's up to you.
b. Into that directory, copy the files
/home/rebelsky/share/c/buggy/debugme.c and
/home/rebelsky/share/c/buggy/segfault.c.
c. Copy the sample program from the sample session of the DDD tutorial, available at
.
d. Create your standard Makefile. Add -g to the C flags.
e. Add the following lines to your Makefile. These tell make to recompile
sample if the Makefile changes.
sample: sample.c Makefile
$(CC) $(CFLAGS) -o sample sample.c
In this exercise, you will follow the steps in the DDD Sample Session,
available at
.
Unfortunately, the sample code contains some C syntax that we have
not studied yet, so you may not understand everything in the sample
program. However, you will still learn a lot about the use of the
debugger, and that is the point of this laboratory lesson.
a. Follow the instructions in the sample tutorial, except for the
exceptions listed below. Stop at the end of the tutorial (i.e., when
you run into the sample source code again), which is way before
the end of the Web page.
* In many places, the tutorial suggests further reading in the form (see
Topic Name)
. I suggest that you skip these additional readings on
your first pass through the tutorial. If you have extra time and
inclination, you can follow these links later.
* On some systems, the bug in the program does not show itself when
using sample data suggested in the tutorial. However, it does seem to
appear if you multiply all of the suggested values by 100. This may be
system (and moment) dependent, given the nature of the bug. I suggest
you start by trying the original examples, and if the bug does not appear,
use even larger values.
* You may want to add an & after
the command when you invoke ddd. As usual, this allows
you to run the program without disabling your terminal window.
b. Return to the top of GNU's tutorial, and scan through it again, this
time making a crib sheet of the various DDD features you learned. I suggest
recording how the various features are invoked and also brief descriptions
of what they do. You may want to keep this crib sheet handy for future use!
Note that we will reflect as a group on what you put on your crib sheet.
a. Compile the program sample.c again, this time without
using the option -g, and try to run it in DDD. (The
purpose of this exercise is so that you may recognize the error it
produces should you happen to see it again in the future.) Recall
that you'll need to update the Makefile, update sample.c
(using touch sample.c) before you use make
to recompile.
b. Recompile sample.c with the debugging information
included. (Again: Update the Makefile, touch sample.c,
run make.) Run ddd again. Move the mouse over various
icons on the toolbar, and press the F1 key over some of them to
read about what they do.
c. Try selecting What Now? from the Help menu (in the
far upper-right corner of the DDD window). You may also want to try the
Tip of the Day from the same menu.
a. Use what you have learned to track down and fix the bugs in
debugme.c with the help of DDD.
You may find the Interrupt button on the DDD Command Tool
useful for this exercise. It will suspend your program -- a
useful feature for locating infinite loops.
At some point during this exercise, try moving a breakpoint from one line
to another by dragging the "stop sign" icon.
a. Read through segfault.c so that you understand what it
does. If you see any bugs, please leave them in place for now.
b. Next, compile the program, and just for this once ignore the
warning that it gives. When you run the program, it will probably throw a
segmentation fault.
c. DDD can be very helpful in locating segmentation faults! To see this,
open the program in DDD, and then press Run to run the program
without any breakpoints.
Notice that the prompt for input values is shown in DDD's lower pane. You
should go ahead and enter the numbers the program is asking for
there. However, I expect that you will get a segmentation fault during that
process.
Notice the segmentation fault error message, which also appears in DDD's
lower pane. At this point, your program is no longer running. However, DDD
can still help you find the problem.
Select Status->Backtrace from the DDD menu. A dialog window,
titled "DDD: Backtrace", should open. You can widen the window by dragging
its right edge.
You will see a list of three functions displayed in that window. This
"backtrace" gives the current "function call stack" (ie, the sequence of
function calls that are currently active). In this example, it tells you
that main() is running, and within main(), a call
to scanf() has been
made. Further, within scanf() a call to _IO_vfscanf() has
been made. This is where the program crashed... but the bug happened earlier.
Look again at the top line of the backtrace:
#2 0x08048444 in main () at segfault.c:12
This tells you the segmentation fault happened at line 12 in main().
With this information, you should be able to find and fix this bug.
If you are interested in learning more about the Shell Sort algorithm
used in GNU's DDD tutorial, you can read about it on Wikipedia.
February 2007 [Marge Coahran]
* Created.
Monday, 11 October 2010 [Samuel A. Rebelsky]
* Reformatted. Rewrote some text.
Monday, 11 April 2011 [Samuel A. Rebelsky]
* Minor cleanup.
* This version available at
.