Debugging and GDB

COMP2521 20T2 - Debugging ♢ [0/27]
❖ Debugging


Debugging needed when software "does not behave as expected".

I.e. when results are different to those implied by the specification.

Typically:


Bug: fragment of code that does not satisfy its specification.
COMP2521 20T2 - Debugging ♢ [1/27]
❖ ... Debugging

Consequences of bugs:

Simple example of buggy program:

int main(int argc, char *argv[]) {
   int i, sum;
   for (i = 1; i <= argc; i++)
      sum += atoi(args[i]);
   printf(sum);
}

COMP2521 20T2 - Debugging ♢ [2/27]
❖ ... Debugging

Debugging has three aspects:

Generally ... (Although sometimes fixing a bug might require substantial re-development)
COMP2521 20T2 - Debugging ♢ [3/27]
❖ ... Debugging


To understand a bug, once a small buggy region of code is isolated

So what is the program state?

Essentially, it's the names/values of all active variables.

COMP2521 20T2 - Debugging ♢ [4/27]
❖ ... Debugging

Model of state/memory of executing C program:

[Diagram:Pics/Cmemory.png]

Active regions are shown in red.

Each function call adds a new stack frame:

COMP2521 20T2 - Debugging ♢ [5/27]
❖ ... Debugging

The real difficulty of debugging is locating the bug.

A bug is a code fragment with unintended action

To repair it, you need to know:

In any real program, the sheer amount of detail is the problem.

Trick to effective debugging: narrowing the focus of attention.

i.e. use a search strategy that enables you to zoom in on the bug.

COMP2521 20T2 - Debugging ♢ [6/27]
❖ Debugging Search Strategy


When you run a buggy program, initially everything is ok.

At some point, the buggy statement is executed ...

Aim: identify a region of code where state becomes "corrupted".

Requires you to know the state* at points during execution.

(* not the whole state (too big), just the interesting bits)

COMP2521 20T2 - Debugging ♢ [7/27]
❖ ... Debugging Search Strategy


A simple search strategy for debugging is as follows:

  1. program prints incorrect result
  2. which variable contains the incorrect value
  3. what was the last statement that set its value
  4. print values of other variables in that statement
  5. restrict attention to variables with wrong values
  6. repeat the above, from step 2
COMP2521 20T2 - Debugging ♢ [8/27]
❖ ... Debugging Search Strategy

A more general strategy:

How to determine strategic points? e.g.
COMP2521 20T2 - Debugging ♢ [9/27]
❖ Examining Program State

A vital tool for debugging is a mechanism to display state.

E.g. diagnostic print statements of "suspect" variables.

Problems with this approach:

(The last problem can be handled by writing yet another program to process the diagnostic output.)
COMP2521 20T2 - Debugging ♢ [10/27]
❖ ... Examining Program State


An alternative for obtaining access to program state:

This is exactly the functionality provided by debuggers (e.g. gdb).


One useful special case ...

COMP2521 20T2 - Debugging ♢ [11/27]
❖ C Program Execution

Under Linux, a C program executes either:


Executing Java and Python programs produce similar behaviour.

However, because they are interpreted, they may give informative error messages from run-time errors.

Note that dcc tries to achieve something similar for C programs

COMP2521 20T2 - Debugging ♢ [12/27]
❖ Normal Program Execution

An executing program has multiple ways of getting data in and out.

[Diagram:Pics/unixproc.png]


The program runs autonomously until it finishes execution.
COMP2521 20T2 - Debugging ♢ [13/27]
❖ Program Execution with Debugger

GDB adds ability to control execution and observe state interactively.

[Diagram:Pics/gdbproc.png]

COMP2521 20T2 - Debugging ♢ [14/27]
❖ Debuggers

A debugger gives control of program execution:


gdb command is a command-line-based debugger for C,C++ ...

There are GUI front-ends available (e.g. xxgdb, ddd, ...).

GUI development environments typically have a built-in debugger.

COMP2521 20T2 - Debugging ♢ [15/27]
❖ ... Debuggers

To use programs with gdb, must be compiled with the -g flag.

$ gcc -g -o myprog myprog.c

gdb takes one or two command line arguments:

$ gdb executable [core]

E.g.

$ gdb  a.out  core
$ gdb  myprog

The core argument is optional.

COMP2521 20T2 - Debugging ♢ [16/27]
gdb Sessions

gdb is like a shell to control and monitor an executing C program.

Example session:

$ gcc -g -o prog prog.c
$ gdb -q prog
Reading symbols from prog ...done.
(gdb) break f
Breakpoint 1 at 0x1082c: file prog.c, line 32.
(gdb) run
Starting program: ..../prog 
Enter a b c: 1 2 3
Breakpoint 1, f (i=1, j=2) at prog.c:32
32              a = i + j;
(gdb) next
33              b = i*i + j*j;
(gdb) next
34              return a*b;
(gdb) print a
$1 = 3
(gdb) print b
$2 = 5
(gdb) cont
...

COMP2521 20T2 - Debugging ♢ [17/27]
❖ Basic gdb Commands


quit -- quits from gdb

help [CMD] -- on-line help

Gives information about CMD command.

run ARGS -- run the program

ARGS are whatever you normally use, e.g.

$ xyz  42  <  data

is achieved by:

(gdb) run  42  <  data

COMP2521 20T2 - Debugging ♢ [18/27]
gdb Status Commands

where -- stack trace

Find which function the program was executing when it crashed.

Stack may also have references to system error-handling functions.

up [N] -- move down the stack

Allows you to skip to scope of particular procedure in stack.

list [LINE] --- show code

Displays five lines either side of current statement.

COMP2521 20T2 - Debugging ♢ [19/27]
❖ ... gdb Status Commands

print EXPR -- display expression values

EXPR can be (almost) almost any expression

print x
print a[5]
print a[i]
print stu[2].name
print cur->val
print cur->next->val

EXPR may use (current values of) variables.

Special expression a@1 shows all of the array a.

COMP2521 20T2 - Debugging ♢ [20/27]
gdb Execution Commands

break [PROC|LINE] - set break-point

On entry to procedure PROC (or reaching line LINE), stop execution and return control to gdb.

next - single step (over procedures)

Execute next statement; if statement is a procedure call, execute entire procedure body.

step - single step (into procedures)

Execute next statement; if statement is a procedure call, go to first statement in procedure body.

For more details see gdb's on-line help.

COMP2521 20T2 - Debugging ♢ [21/27]
❖ Using a Debugger

Most common time to invoke a debugger: after a run-time error.

If this produces a core file, try

$ gdb -q prog core

The where command can tell you where the program crashed

Where the program crashed ...

COMP2521 20T2 - Debugging ♢ [22/27]
❖ ... Using a Debugger


Once you have an idea where the bug might be:

This will eventually reveal a variable with an incorrect value.
COMP2521 20T2 - Debugging ♢ [23/27]
❖ ... Using a Debugger

Once you find that the value of a given variable (e.g. x) is wrong, the next step is to determine why it is wrong.

Two possibilities:

Example:   if (c > 0) x = a + b;

If we know that

then we need to find out where a, b and c were set.
COMP2521 20T2 - Debugging ♢ [24/27]
❖ Other Debugging Ideas


Debugging is an example of applying a kind of scientific method:

A potential hypothesis in the context of debugging:

"I think the bug is this statement here ..."

COMP2521 20T2 - Debugging ♢ [25/27]
❖ Laws of Debugging

Courtesy of Zoltan Somogyi, Melbourne University

Before you can fix it, you must be able to break it (consistently).

(non-reproducible bugs ... Heisenbugs ... are extremely difficult to deal with)

Bug not where you're looking? You're looking in the wrong place.

(taking a break and resuming the debugging task later is generally a good idea)

It takes two people to find a subtle bug, but only one of them needs to know the program.

(the second person asks questions to challenge the debugger's assumptions)

(In fact, sometimes the second person doesn't have to do or say anything! The process of explaining the problem is often enough to trigger a Eureka event.)

COMP2521 20T2 - Debugging ♢ [26/27]
❖ Possibly Untrue Assumptions

Debugging can be extremely frustrating when you make assumptions about the problem which turn out to be wrong.

Some things to be wary of:

COMP2521 20T2 - Debugging ♢ [27/27]


Produced: 2 Jun 2020