Noeud:Fun With Uninitialised Variables, Noeud « Next »:Try Again - Again..., Noeud « Previous »:The Third Bug, Noeud « Up »:An example debugging session using gdb
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
.