Noeud:Fun With Uninitialised Variables, Noeud « Next »:, Noeud « Previous »:The Third Bug, Noeud « Up »:An example debugging session using gdb



Fun With Uninitialised Variables

     bash$ gdb ecount3
     (gdb) b main
     Breakpoint 1 at 0x8048496: file ecount3.c, line 18.
     (gdb) r example
     Starting program: /home/paul/gnuprog2/src/debugging/ecount3 example
     
     Breakpoint 1, main (argc=2, argv=0xbffff914) at ecount3.c:18
     18	  if( argc == 1 )
     (gdb) n
     26	  strcpy( buf, argv[1] );
     

Now we are on the line that first uses the string we supplied. We could test it here, but gdb prints the line we are *about to execute*, not the line just done. So buf won't yet have the string in it. Let's move on one more line and see what's in buf then.

     (gdb) n
     34	  for( i=0; i<strlen(buf); ++i )
     (gdb) p buf
     $1 = "example\000Èø"
     

So buf does have the right string in it - but gdb has printed the whole of the char array, since it knows how long it is. This leads to it showing the '\0' on the end, plus some trailing garbage. Usually we could just ignore that, but for the purposes of the example I'll tidy it up.

     (gdb) set print null-stop
     (gdb) p buf
     $4 = "example"
     

set print null-stop tells gdb to treat char arrays like C strings, and stop when it reaches a '\0'.

Now let's get back to this crazy value for count. We'll start off by printing it's value before we've done anything to it.

     (gdb) p count
     $6 = 1074045240
     

Aha! It starts off with a very high value - we forgot to initialise it in the first place. Rather than go through the whole edit-recompile-build cycle again, let's use a powerful feature of gdb and edit it in place.

     (gdb) set count=0
     (gdb) p count
     $7 = 0
     

So now it's initialised as it should be (and will be once we've put it right....if we remember!).

We are at the start of the loop that counts 'e's, so let's step inside it then have a good look at what goes on during the loop. Here we *could* use print after every step, but if we use display instead, then gdb will automatically print the values every time it stops.

     (gdb) n
     36      if( buf[i] == 'e' ) ++count;
     (gdb) display count
     1: count = 0
     (gdb) display buf[i]
     2: buf[i] = 101 'e'
     

Now we can step through the loop and watch the value of count change along with the letter it's currently examining.

     (gdb) n
     34	  for( i=0; i<strlen(buf); ++i )
     2: buf[i] = 101 'e'
     1: count = 1
     (gdb) n
     36	    if( buf[i] == 'e' ) ++count;
     2: buf[i] = 120 'x'
     1: count = 1
     (gdb) n
     34	  for( i=0; i<strlen(buf); ++i )
     2: buf[i] = 120 'x'
     1: count = 1
     (gdb) n
     36	    if( buf[i] == 'e' ) ++count;
     2: buf[i] = 97 'a'
     1: count = 1
     (gdb) n
     34	  for( i=0; i<strlen(buf); ++i )
     2: buf[i] = 97 'a'
     1: count = 1
     (gdb) n
     36	    if( buf[i] == 'e' ) ++count;
     2: buf[i] = 109 'm'
     1: count = 1
     (gdb) n
     34	  for( i=0; i<strlen(buf); ++i )
     2: buf[i] = 109 'm'
     1: count = 1
     (gdb) n
     36	    if( buf[i] == 'e' ) ++count;
     2: buf[i] = 112 'p'
     1: count = 1
     (gdb) n
     34	  for( i=0; i<strlen(buf); ++i )
     2: buf[i] = 112 'p'
     1: count = 1
     (gdb) n
     36	    if( buf[i] == 'e' ) ++count;
     2: buf[i] = 108 'l'
     1: count = 1
     (gdb) n
     34	  for( i=0; i<strlen(buf); ++i )
     2: buf[i] = 108 'l'
     1: count = 1
     (gdb) n
     36	    if( buf[i] == 'e' ) ++count;
     2: buf[i] = 101 'e'
     1: count = 1
     (gdb) n
     34	  for( i=0; i<strlen(buf); ++i )
     2: buf[i] = 101 'e'
     1: count = 2
     (gdb) n
     39	  printf( "There are %d 'e's in '%s'.\n", count, buf );
     2: buf[i] = 0 '\000'
     1: count = 2
     

So now we've stepped through the loop and found the two 'e's correctly. The two display expressions are still active, so we'd better stop them.

     (gdb) undisplay
     Delete all auto-display expressions? (y or n) y
     (gdb) n
     There are 2 'e's in 'example'.
     

All looks good so far, once we've made the change to the initialisation of count.