I l@ve RuBoard |
![]() ![]() |
17.4 Interactive DebuggersMost compiler manufacturers provide an interactive debugger. They give you the ability to stop the program at any point, examine and change variables, and "single-step" through the program. Because each debugger is different, a detailed discussion of each tool is not possible.
17.4.1 Basic Debugging CommandsHowever, we are going to discuss one debugger: GDB. This program is available for many Unix machines from the Free Software Foundation. Borland-C++ and Visual C++ have their own built-in debuggers. Although the exact syntax used by your debugger may be different, the principles shown here will work for all debuggers. Basic GDB commands are the following:
17.4.2 Debugging a Simple ProgramWe have a program that should count the number of threes and sevens in a series of numbers. The problem is that it keeps getting the wrong answer for the number of sevens. Our program is shown in Example 17-1. Example 17-1. seven/count.cpp1: #include <iostream> 2: 3: int seven_count; /* number of seven's in the data */ 4: int data[5]; /* the data to count 3 and 7 in */ 5: int three_count; /* the number of threes in the data */ 6: 7: int main( ) { 8: int index; /* index into the data */ 9: void get_data(int data[]); 10: 11: seven_count = 0; 12: three_count = 0; 13: get_data(data); 14: 15: for (index = 1; index <= 5; ++index) { 16: if (data[index] == 3) 17: ++three_count; 18: if (data[index] == 7) 19: ++seven_count; 20: } 21: std::cout << "Three's " << three_count << 22: " Seven's " << seven_count << '\n'; 23: return (0); 24: } 25: /******************************************************** 26: * get_data -- get 5 numbers from the command line * 27: ********************************************************/ 28: void get_data(int data[]) 29: { 30: std::cout << "Enter 5 numbers\n"; 31: std::cin >> data[1] >> data[2] >> data[3] >> data[4] >> data[5]; 32: } When we run this program with the data 3 7 3 0 2, the results are: Threes 3 Sevens 3 We start by invoking the debugger (GDB) with the name of the program we are going to debug (count). The debugger initializes, outputs the prompt (gdb), and waits for a command. % gdb count 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.12 (m68k-sun-sunos4.0.3), Copyright 1994 Free Software Foundation, Inc... (gdb) We don't know where the variable is getting changed, so we'll start at the beginning and work our way through until we get an error. At every step, we'll display the variable seven_count just to make sure it's okay. We need to stop the program at the beginning so we can single-step through it. The command break main tells GDB to set a breakpoint at the first instruction of the function main: (gdb) break main Breakpoint 1 at 0x22c2: file count.cpp, line 12. (gdb) The number 1 is used by GDB to identify the breakpoint. Now we need to start the program. The command run tells GDB to start the program, which will run until it hits the first breakpoint: (gdb) run Starting program: /usr/sdo/count/count Breakpoint 1, main ( ) at count.cpp:12 11 seven_count = 0; (gdb) The message Breakpoint 1, main... indicates that the program encountered a breakpoint and has now turned control over to debug. We have reached the point where seven_count is initialized. The command next will execute a single statement, treating function calls as one statement. (The name of the command for your debugger may be different.) We go past the initialization and check to see whether it worked: (gdb) next 12 three_count = 0; (gdb) print seven_count $1 = 0 (gdb) Initialization worked. We try the next few lines, checking all the time: (gdb) next 13 get_data(data); (gdb) print seven_count $2 = 0 (gdb) next Enter 5 numbers 3 7 3 0 2 15 for (index = 1; index <= 5; ++index) { (gdb) print seven_count $3 = 2 (gdb) seven_count somehow changed the value to 2. The last statement we executed was get_data(data); so something is going on in that function. We add a breakpoint at the beginning of get_data, get rid of the one at main, and start the program over with the run command: (gdb) break get_data Breakpoint 2 at 0x23b2: file count.cpp, line 30. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x000022c2 in main at count.cpp:11 2 breakpoint keep y 0x000023b2 in get_data(int *) at count.cpp:30 (gdb) delete 1 (gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) Y Starting program: /usr/sdo/count/count Breakpoint 2, get_data (data=0x208f8) at count.cpp:30 (gdb) We now start single-stepping again until we find the error: Breakpoint 2, get_data (data=0x208f8) at count.cpp:30 30 std::cout << "Enter 5 numbers\n"; (gdb) print seven_count $5 = 0 (gdb) next 31 std::cin >> data[1] >> data[2] >> data[3] >> data[4] >> data[5]; (gdb) print seven_count $6 = 0 (gdb) next Enter 5 numbers 3 7 3 0 2 32 } (gdb) print seven_count $7 = 2 (gdb) list 23 23 return (0); 24 } 25 /******************************************************** 26 * get_data -- get 5 numbers from the command line * 27 ********************************************************/ 28 void get_data(int data[]) 29 { 30 std::cout << "Enter 5 numbers\n"; 31 std::cin >> data[1] >> data[2] >> data[3] >> data[4] >> data[5]; 32 } At line 32 the data was good, but when we reached line 33, the data was bad, so the error is located at line 33 of the program, the std::cin. We've narrowed the problem down to one statement. By inspection, we can see that we are using data[5], an illegal member of the array data. But why does seven_count go bad? Since data is only five elements long, there is no data[5]. However, the std::cin >> data[5] has to put the data someplace, so it decided to put it in a random memory location, in this case seven_count. ![]() |
I l@ve RuBoard |
![]() ![]() |