next up previous
Next: More information Up: Tracing code Previous: An example in

An example in C++

Suppose we've implemented a very simple linked class:

#include <iostream.h>


class node
{
public:
    node(int i, node* n) { item_ = i; next_ = n; }

    int item() { return item_; }
    node* next() { return next_; }

protected:
    int item_;
    node* next_;
};


int main()
{
    int i;
    node* current = 0;

// build list
    node* head = new node(1, NULL);
    head = new node(2, head);       // prepend new node
    head = new node(3, head);       // prepend new node

// print list
    current = head;
    for (i = 0; i <= 3; i++)        // since list-size is now 3
    {
        cout << "item " << i << " is " << current -> item() << endl;
        current = current -> next();
    }

// destroy list
    current = head;
    for (i = 0; i <= 3; i++)
    {
        current = head -> next();
        delete head;
        head = current;
    }

    return 0;
}
It looks quite simple, but it still contains a bug:
 g++ -g -o list list.cc
 list
item 0 is 3
item 1 is 2
item 2 is 1
Memory fault

First, we let GDB pinpoint the exact location of the memory fault:
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.13 (sparc-sun-solaris2.3), 
Copyright 1994 Free Software Foundation, Inc...
 gdb list
(gdb) run
Starting program: /home/se/doc/debug/source/list 
item 0 is 3
item 1 is 2
item 2 is 1

Program received signal SIGSEGV, Segmentation fault.
node::item (this=0x0) at list.cc:9
9           int item() { return item_; }
(gdb)
If the information provided by GDB is examined closely, it appears that the this-pointer is 0! This means a member function is called for a non-existing object and this will indeed cause a memory fault. But how can this happen? Use the command bt to show the calling sequence that resulted in the memory fault:
(gdb) bt
#0  node::item (this=0x0) at list.cc:9
#1  0x800896e in main () at list.cc:32
(gdb) list list.cc:32
27
28      // print list
29          current = head;
30          for (i = 0; i <= 3; i++)        // since list-size is now 3
31          {
32              cout << "item " << i << " is " << current -> item() << endl;
33              current = current -> next();
34          }
35
36      // destroy list
(gdb)
It appears something goes wrong while printing all values. Since current is always pointing to the current object, it follows that current is at some point set to 0. But current can only be 0 at the end of the list (when next_ equals 0). Let's see what happens when the last item has been printed:
(gdb) br list.cc:32
Breakpoint 1 at 0x8008940: file list.cc, line 32.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/se/doc/debug/source/list 

Breakpoint 1, main () at list.cc:32
32              cout << "item " << i << " is " << current -> item() << endl;
(gdb) cont
Continuing.
item 0 is 3

Breakpoint 1, main () at list.cc:32
32              cout << "item " << i << " is " << current -> item() << endl;
(gdb) cont
Continuing.
item 1 is 2

Breakpoint 1, main () at list.cc:32
32              cout << "item " << i << " is " << current -> item() << endl;
(gdb)
So far, so good. This is the last item to be printed (since there are only 3 list-nodes). We now use tracing to see what happens next:
(gdb) n
item 2 is 1
33              current = current -> next();
(gdb) n
34          }
(gdb) print current
$1 = (node *) 0x0
(gdb)
As expected, current is now 0. But what happens now?
(gdb) n
32              cout << "item " << i << " is " << current -> item() << endl;
(gdb)
It appears the loop is not finished yet! How can that be?
(gdb) print i
$2 = 3
(gdb)
After some thinking, the problem is clear: the loop is executed four times instead of three times. The for-loop should be for (i = 0; i < 3; i++) { ... } and then it will work (the second loop should of course be changed also).



SE Praktikum
Tue Aug 13 11:13:23 MET DST 1996