Lecture #17 – Debugging

 

 

To debug an application, you must first compile with symbol names saved into the executable.  This allows the debugger to examine variables and set breakpoints.

 

$  cc –g ex13.c –o ex13

 

The “-g” option tells the compiler to “generate” symbol information.

 

 

Once you have a program compiled with symbols, you can start running it in the debugger as follows:

 

$ gdb ex13

 

This will load the program into the debugger, but will not start execution.

 

You should get a prompt that looks something like:

 

(gdb)

 

To list the source type:

 

(gdb) list

1       #include <stdio.h>

2

3       main (int argc, char *argv[])

4       {

5               char *buf;

6               FILE *infp, *outfp;

7

8               if (argc < 3)

9               {

10                      fprintf(stderr, "Usage: <input> <output>\n");

(gdb)

 

 

To start running at the first list, first set a breakpoint:

 

(gdb) break 8

 

Where in this case the first line is number 8.

 

Running the program will then start the application and continue until a breakpoint is encountered.

 

(gdb) run

Starting program: /home/home2/csuser/ceichelk/cs390/homework5/ex13

 

Breakpoint 1, main (argc=1, argv=0xbffffc04) at ex13.c:8

8               if (argc < 3)

(gdb) list

 

To examine a variable use the “print” command:

 

(gdb) print argc

$1 = 1

(gdb)

 

There are to commands to single step within the debugger – “step” and “next”.

 

Use “step” to enter into a function.

 

Use “next” to step over a function.

 

For normal statements without a function, “step” and “next” do the same thing.

 

 

help                              = prints a list of commands

 

run arg1 arg2 arg3…    = runs the program with command line arguments

 

step                              = step a single line, step into a function.

 

next                              = step a single line, step over a function.

 

continue                        = run until the next breakpoint.

 

break ##                       = break a line ##

 

break name                  = break a function “name”

 

clear                             = remove all breakpoints

 

print expr                      = evaluate the expression and then print the results

 

printf “%d\n”,expr         = evaluate the expression and print formatted using printf

whatis   name                = displays the datatype of the variable name

 

info stack                      = displays the list of routines that got us to this line

 

quit                               = exit the debugger

 

 

When an application fails, UNIX will automatically create a “core” dump that can be used by the debugger to show where the error occurred.

 

$ ex13 data.txt output.txt

Segmentation fault (core dumped)

$

 

 

The file is names “core” and is located in the current working directory.

 

It is possible to disable the generation of the “core” dump, but setting the resource limit of the file to zero.

 

$ limit

cputime                        unlimited

filesize                          unlimited

datasize                        unlimited

stacksize                       8192 kbytes

coredumpsize               0 kbytes

memoryuse                   unlimited

descriptors                   1024

memorylocked              unlimited

maxproc                       1023

openfiles                       1024

 

By default, UAH has the coredumpsize set to 0.  This disables coredump.

 

To re-enable coredump, use something like the following:

 

$ limit coredumpsize 1024

 

 

After a core dump, you can load the image into the debugger with:

 

$ gdb ex13 core

 

You will probably want to use the “info stack” command to see where the program failed.