brief introduction
When using the graphical ide for program development, the editing tool usually has its own debugging function, which can interrupt the point, execute the code step by step and view the real-time value of each variable at any time. However, when developing c and c + +, it is often carried out under linux system, and through vim or vi editor, without graphical interface, This is the use of GDB debugging tool. It provides most of the functions we need when debugging programs. This article is the author's learning notes on the use of GDB tools in the Book Linux C programming: one-stop learning.
1. Single step execution and trace function call
1.1 example program
First read the following code. The main function of this code is to realize the accumulation of numbers
#include <stdio.h> int add_range(int low, int hight) { int i, sum; for(i = low; i <= hight; i++) { sum += i; } return sum; } int main() { int res1, res2; res1 = add_range(1, 10); res2 = add_range(1, 100); printf("res1 = %d, res2 = %d\n", res, res2); return 0; }
The following are the operation results given in the book
res1 = 55, res2 = 5105
However, interestingly, after the author runs it himself, he finds that the output result given by the author of the original book does not appear, and the author knows that it will not appear, because the variable sum is not initialized after it is defined. The result in the book may be the output result specially set by the author for gdb debugging, which does not hinder learning. The following is the output of the author's running program
zz@ubuntu:~/Project/gdb_study$ ./demo1 res1 = 21911, res2 = 26961 zz@ubuntu:~/Project/gdb_study$ ./demo1 res1 = 22009, res2 = 27059 zz@ubuntu:~/Project/gdb_study$ ./demo1 res1 = 22012, res2 = 27062 zz@ubuntu:~/Project/gdb_study$ ./demo1 res1 = 22051, res2 = 27101 zz@ubuntu:~/Project/gdb_study$ ./demo1 res1 = 22155, res2 = 27205 zz@ubuntu:~/Project/gdb_study$ ./demo1 res1 = 22001, res2 = 27051 zz@ubuntu:~/Project/gdb_study$ ./demo1 res1 = 22016, res2 = 27066
It can be seen that the result changes all the time, which is very consistent with the result that the variable is used without initialization. After we assign a value of 0 to sum, the program will run normally and output the result we want. Let's assume that we don't know what's wrong. After the program runs and outputs, we pretend to be confused. At this time, gdb should play.
1.2 common commands
Run the following command
gcc -g demo1.c -o demo1 gdb demo1
When compiling, adding the compiling option - g means adding the information of the source code into the executable file. For example, the first machine instruction in the executable file corresponds to the first line of the source code, but the whole source file is not embedded into the executable file. Therefore, gdb must be able to find the source file during debugging.
1.2.1 help
For help commands, you can view the category of commands or specify the specific description of a command
(gdb) help List of classes of commands: aliases -- Aliases of other commands. breakpoints -- Making program stop at certain points. data -- Examining data. files -- Specifying and examining files. internals -- Maintenance commands. obscure -- Obscure features. running -- Running the program. stack -- Examining the stack. status -- Status inquiries. support -- Support facilities. tracepoints -- Tracing of program execution without stopping the program. user-defined -- User-defined commands. Type "help" followed by a class name for a list of commands in that class. Type "help all" for the list of all commands. Type "help" followed by command name for full documentation. Type "apropos word" to search for commands related to "word". Type "apropos -v word" for full documentation of commands related to "word". Command name abbreviations are allowed if unambiguous.
1.2.2 list (l)
List the contents of the source code, run the command once and display 10 lines. You need to continue browsing. Just press enter and execute the last command by default
(gdb) list 1 #include <stdio.h> 2 3 int add_range(int low, int hight) 4 { 5 int i, sum; 6 for(i = low; i <= hight; i++) 7 { 8 sum += i; 9 } 10 return sum; (gdb) 11 } 12 13 int main() 14 { 15 int res1, res2; 16 res1 = add_range(1, 10); 17 res2 = add_range(1, 100); 18 printf("res1 = %d, res2 = %d\n", res1, res2); 19 return 0; 20 } (gdb)
1.2.3 quit
Exit command, push gdb Debugging environment
1.2.4 start
Program start command
(gdb) start Temporary breakpoint 1 at 0x1176: file demo1.c, line 14. Starting program: /home/zz/Project/gdb_study/demo1 Temporary breakpoint 1, main () at demo1.c:14 14 {
After running this command, you can find that it automatically jumps to the beginning of the main function and indicates the line number.
1.2.5 next(n)
Continue to execute the command and control the program to execute the next line
(gdb) next 16 res1 = add_range(1, 10); (gdb) 17 res2 = add_range(1, 100); (gdb) 18 printf("res1 = %d, res2 = %d\n", res1, res2); (gdb) res1 = 21900, res2 = 26950 19 return 0; (gdb) 20 } (gdb)
1.2.6 step(s)
Trace the function entered and executed
After calling the next command all the way, we found that we did not find any exceptions. Maybe the program error is not in the main function, but in the function called in the main function. But the next command is executed, the system will skip the function automatically. If you want to enter the function step by step, you will need the step command to track the program.
(gdb) start Temporary breakpoint 2 at 0x555555555176: file demo1.c, line 14. Starting program: /home/zz/Project/gdb_study/demo1 Temporary breakpoint 2, main () at demo1.c:14 14 { (gdb) next 16 res1 = add_range(1, 10); (gdb) step add_range (low=21845, hight=1431654941) at demo1.c:4 4 {
From above, enter add_ After the range function, the formal parameters are given messy values, which is different from what we expected and what is said in the book. I won't explain it here, and the author will have some personal conjectures later.
1.2.7 backtrace(bt)
View stack frame of function call
(gdb) bt #0 add_range (low=21845, hight=1431654941) at demo1.c:4 #1 0x0000555555555191 in main () at demo1.c:16
1.2.8 info(i)
View the value of the parameter
- Info localsview local parameters
- info arg view function parameters
(gdb) i locals i = 1431654864 sum = 21845 (gdb) info locals i = 1431654864 sum = 21845 (gdb) info arg low = 21845 hight = 1431654941
It can be seen that the local parameters and formal parameters of the function are messy values. The author guesses that at this time, the function has just been pushed into the stack, the memory has just been allocated, the formal parameters and local parameters have been created, and the assignment of the actual parameters to the formal parameters has not been completed. We are going to take the next step.
(gdb) n 6 for(i = low; i <= hight; i++) (gdb) info locals i = 1431654864 sum = 21845 (gdb) info arg low = 1 hight = 10 (gdb)
It can be seen that when the function is executed to the sixth line, the local parameter is garbled because it has not been initialized and has been assigned, but the formal parameter can be seen to be the correct value, indicating that the actual parameter has successfully assigned the formal parameter.
1.2.9 frame(f)
Function stack frame switching
At this point, the program is already in add_ In the range function, what should I do if I want to view the parameter information in the main function? Use the frame command to switch the frame of the function stack
(gdb) bt #0 add_arrange (low=1, hight=10) at demo1.c:6 #1 0x0000555555555191 in main () at demo1.c:16 (gdb) frame 1 #1 0x0000555555555191 in main () at demo1.c:16 16 res1 = add_arrange(1, 10); (gdb) i locals res1 = 0 res2 = 0 (gdb) f 0 #0 add_arrange (low=1, hight=10) at demo1.c:6 6 for(i = low; i <= hight; i++)
As you can see, use the backtrace command to view the current function stack frame information, and use the frame function stack frame number command to switch to the specified function stack frame. At this time, use the info locals command to view the values of local parameters in the current main function. After viewing, use the frame command to switch to add_range function, you can see that it is still in the place where the previous function runs.
1.2.10 print§
Print the value of the variable
(gdb) print sum $1 = 21845
Here, $1 means that gdb saves these intermediate results, and the number after $1 will increase automatically. You can replace the corresponding value with $1, $2, $3 and other numbers in the command.
1.2.11 set var
Set the variable to the specified value
At this time, we already know that the program error is caused by the reason that sum is not initialized. In order to verify our idea, we initialize sum manually to see whether the result is what we expect.
(gdb) set var sum=0 (gdb) print sum $4 = 0
1.2.12 finish
Run continuously until the current function returns, and then stop and wait for the command
(gdb) finish Run till exit from #0 add_arrange (low=1, hight=10) at demo1.c:6 0x0000555555555191 in main () at demo1.c:16 16 res1 = add_arrange(1, 10); Value returned is $5 = 55
It can be seen that the function runs successfully to the end and the return value is 55, which shows that our idea is completely correct. The program error is due to the uninitialization of sum variable.
1.3 command summary
command | describe |
---|---|
backtrace(bt) | View function calls and parameters at all levels |
finish | Run continuously until the current function returns, and then stop and wait for the command |
frame(f) | Select function stack frame |
info(i) | View current parameter information (locals: view local variable parameters; arg: View function parameter values; registers: view current register data) |
list(l) | List the source code, 10 lines at a time, with memory, and list it down after the last listing (add the line number after it, and list the code from this line number; add the function name after it: list the code of this function) |
next(n) | Execute the next statement |
print§ | Print the value of the expression, through which you can modify the value of the variable or call the function |
quit(q) | Exit gdb debugging environment |
set var | Modify the value of the variable |
start | Start executing the program, stay in front of the first line of the main function and wait for the command |
step(s) | Execute the next statement. If there is a function, enter the function |