GDB调试器
我们在讲指针时用 GDB 调试段错误。
本篇将详细介绍 gdb 的最常用命令、日志记录、检测点,最后介绍如何用 gdb 调试进程以及用gdb 调试一个开源项目的调试版本 —— glmark2。
gdb介绍
GDB, the GNU Project debugger —— gdb官网
gdb 是一款调试器,能打断点。支持多种语言,例如 c、c++、go。
Tip:有关 GNU Project,请看本篇扩展。
官网显示最新版本是13.2(20230704)。点击官网顶部[documentation]可查看文档。
安装GDB
笔者已经用 apt 源安装了gbd:- jjj-pc:~/pj/glmark2$ sudo apt install gdb
- 正在读取软件包列表... 完成
- 正在分析软件包的依赖关系树
- 正在读取状态信息... 完成
- gdb 已经是最新版 (9.1-0kylin1)。
- 下列软件包是自动安装的并且现在不需要了:
- archdetect-deb dmeventd libaio1 libdebian-installer4 libdevmapper-event1.02.1 liblvm2cmd2.03 localechooser-data lvm2 user-setup
- 使用'sudo apt autoremove'来卸载它(它们)。
- 升级了 0 个软件包,新安装了 0 个软件包,要卸载 0 个软件包,有 6 个软件包未被升级。
复制代码 笔者gbd版本是 9.1- jjj-pc:~/pj/glmark2$ gdb --version
- GNU gdb (Ubuntu 9.1-0kylin1) 9.1
- Copyright (C) 2020 Free Software Foundation, Inc.
- License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
- This is free software: you are free to change and redistribute it.
- There is NO WARRANTY, to the extent permitted by law.
复制代码 最常用命令
man gdb 告诉我们最常用的命令有:break、run、print、c、next、list、step、quit。- // 以下是一些最常用的GDB命令:
- Here are some of the most frequently needed GDB commands:
- break [file:]function
- Set a breakpoint at function (in file).
- run [arglist]
- Start your program (with arglist, if specified).
- bt Backtrace: display the program stack.
- print expr
- // 显示表达式的值
- Display the value of an expression.
- c Continue running your program (after stopping, e.g. at a breakpoint).
- next
- // 执行下一条程序语句(在停止后);跳过该行中的任何函数调用。
- Execute next program line (after stopping); step over any function calls in the line.
- edit [file:]function
- look at the program line where it is presently stopped.
- list [file:]function
- type the text of the program in the vicinity of where it is presently stopped.
- step
- Execute next program line (after stopping); step into any function calls in the line.
- help [name]
- Show information about GDB command name, or general information about using GDB.
- quit
- Exit from GDB.
复制代码 准备一段 C 代码用作gdb命令学习:- #include <stdio.h>
- // add 函数
- int add(int a, int b) {
- int sum = a + b;
- return sum;
- }
- int main() {
- int num1 = 3;
- int num2 = 5;
-
- int result = add(num1, num2);
-
- printf("两个整数的和为:%d\n", result);
-
- return 0;
- }
复制代码 run 和 quit
通过 gdb demo 运行进入gdb模式,输入 run 运行程序,输入 quit 则退出gdb。详细请看:- // 通过 -g 编译出有调试信息的可执行文件
- jjj-pc:~/pj$ gcc demo.c -o demo -g
- // gdb 运行
- jjj-pc:~/pj$ gdb demo
- GNU gdb (Ubuntu 9.1-0kylin1) 9.1
- Copyright (C) 2020 Free Software Foundation, Inc.
- License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
- This is free software: you are free to change and redistribute it.
- There is NO WARRANTY, to the extent permitted by law.
- Type "show copying" and "show warranty" for details.
- This GDB was configured as "x86_64-linux-gnu".
- Type "show configuration" for configuration details.
- For bug reporting instructions, please see:
- <http://www.gnu.org/software/gdb/bugs/>.
- Find the GDB manual and other documentation resources online at:
- <http://www.gnu.org/software/gdb/documentation/>.
- For help, type "help".
- Type "apropos word" to search for commands related to "word"...
- Reading symbols from demo...
- // 输入 run 运行程序
- (gdb) run
- Starting program: /home/jjj/pj/demo
- 两个整数的和为:8
- [Inferior 1 (process 3022770) exited normally]
- // 输入 quit 退出
- (gdb) quit
- jjj-pc:~/pj$
复制代码 Tip: ctrl + z 能直接退出gdb
list
如果不知道在哪行或哪个方法打断点,可以通过 list 查看源码。请看示例:- jjj-pc:~/pj$ gdb demo
- GNU gdb (Ubuntu 9.1-0kylin1) 9.1
- Copyright (C) 2020 Free Software Foundation, Inc.
- License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
- This is free software: you are free to change and redistribute it.
- There is NO WARRANTY, to the extent permitted by law.
- Type "show copying" and "show warranty" for details.
- This GDB was configured as "x86_64-linux-gnu".
- Type "show configuration" for configuration details.
- For bug reporting instructions, please see:
- <http://www.gnu.org/software/gdb/bugs/>.
- Find the GDB manual and other documentation resources online at:
- <http://www.gnu.org/software/gdb/documentation/>.
- For help, type "help".
- Type "apropos word" to search for commands related to "word"...
- Reading symbols from demo...
- // 查看源码
- (gdb) list
- 1 #include <stdio.h>
- 2
- 3 // 自定义函数,用于计算两个整数的和
- 4 int add(int a, int b) { // a, b 叫形参
- 5 int sum = a + b;
- 6 return sum;
- 7 }
- 8
- 9 int main() {
- 10 int num1 = 3;
- // 一次显示不完,继续查看后面10行
- (gdb) list
- 11 int num2 = 5;
- 12
- 13 // 调用自定义函数计算两个整数的和
- 14 int result = add(num1, num2);
- 15
- 16 printf("两个整数的和为:%d\n", result);
- 17
- 18 return 0;
- 19 }
- // 到底了。
- (gdb) list
- Line number 20 out of range; demo.c has 19 lines.
- // 查看5到10行
- (gdb) list 5,10
- 5 int sum = a + b;
- 6 return sum;
- 7 }
- 8
- 9 int main() {
- 10 int num1 = 3;
- (gdb)
复制代码 break 和 info break
break(简写 b) 用于打断点,info break 用于查看打了哪些断点。请看示例:- jjj-pc:~/pj$ gdb demo
- GNU gdb (Ubuntu 9.1-0kylin1) 9.1
- Copyright (C) 2020 Free Software Foundation, Inc.
- License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
- This is free software: you are free to change and redistribute it.
- There is NO WARRANTY, to the extent permitted by law.
- Type "show copying" and "show warranty" for details.
- This GDB was configured as "x86_64-linux-gnu".
- Type "show configuration" for configuration details.
- For bug reporting instructions, please see:
- <http://www.gnu.org/software/gdb/bugs/>.
- Find the GDB manual and other documentation resources online at:
- <http://www.gnu.org/software/gdb/documentation/>.
- For help, type "help".
- Type "apropos word" to search for commands related to "word"...
- Reading symbols from demo...
- // 给 mian 方法打断点
- (gdb) break main
- Breakpoint 1 at 0x1167: file demo.c, line 9.
- // 给11行打断点
- (gdb) b 11
- Breakpoint 2 at 0x117a: file demo.c, line 11.
- // 查看打了哪些断点
- (gdb) info b
- Num Type Disp Enb Address What
- 1 breakpoint keep y 0x0000000000001167 in main at demo.c:9
- 2 breakpoint keep y 0x000000000000117a in main at demo.c:11
- // 查看打了哪些断点
- (gdb) info break
- Num Type Disp Enb Address What
- 1 breakpoint keep y 0x0000000000001167 in main at demo.c:9
- 2 breakpoint keep y 0x000000000000117a in main at demo.c:11
复制代码 next 和 step
代码中断后,输入 next 和 step 都会执行下一行,然而 next 会跳过函数,step 会进入函数。请看示例:
- Type "apropos word" to search for commands related to "word"...
- Reading symbols from demo...
- // 打断点
- (gdb) b 9
- Breakpoint 1 at 0x1167: file demo.c, line 9.
- // 运行
- (gdb) run
- Starting program: /home/jjj/pj/demo
- // 在断点处停止
- Breakpoint 1, main () at demo.c:9
- 9 int main() {
- // 下一行
- (gdb) next
- 10 int num1 = 3;
- (gdb) next
- // 下一行
- 11 int num2 = 5;
- (gdb) next
- // 下一行。跳过函数
- 14 int result = add(num1, num2);
- (gdb) next
- // 下一行
- 16 printf("两个整数的和为:%d\n", result);
- (gdb) next
- 两个整数的和为:8
- 18 return 0;
复制代码- Type "apropos word" to search for commands related to "word"...
- Reading symbols from demo...
- (gdb) b 9
- Breakpoint 1 at 0x1167: file demo.c, line 9.
- (gdb) run
- Starting program: /home/jjj/pj/demo
- Breakpoint 1, main () at demo.c:9
- 9 int main() {
- (gdb) step
- 10 int num1 = 3;
- (gdb) step
- 11 int num2 = 5;
- (gdb) step
- 14 int result = add(num1, num2);
- (gdb) step
- add (a=21845, b=1431654909) at demo.c:4
- 4 int add(int a, int b) {
- (gdb) step
- 5 int sum = a + b;
- (gdb) step
- 6 return sum;
- (gdb) step
- 7 }
- (gdb) step
- main () at demo.c:16
- 16 printf("两个整数的和为:%d\n", result);
- (gdb) step
- 两个整数的和为:8
- 18 return 0;
复制代码 continue
next 和 step 会执行下一行,而continue(简写c) 会执行到下一个断点处停止。 请看示例:- Type "apropos word" to search for commands related to "word"...
- Reading symbols from demo...
- // 断点
- (gdb) b main
- Breakpoint 1 at 0x1167: file demo.c, line 9.
- // 断点
- (gdb) b 16
- Breakpoint 2 at 0x1193: file demo.c, line 16.
- // 运行后在第一断点处停止
- (gdb) run
- Starting program: /home/jjj/pj/demo
- Breakpoint 1, main () at demo.c:9
- 9 int main() {
- // 下一个断点
- (gdb) c
- Continuing.
- Breakpoint 2, main () at demo.c:16
- 16 printf("两个整数的和为:%d\n", result);
- (gdb)
复制代码 print
print 用于查看表达式的值。请看示例:- // 在11行打断点,查看 num1
- (gdb) list 9,11
- 9 int main() {
- 10 int num1 = 3;
- 11 int num2 = 5;
- (gdb) b 11
- Breakpoint 1 at 0x117a: file demo.c, line 11.
- (gdb) run
- Starting program: /home/jjj/pj/demo
- Breakpoint 1, main () at demo.c:11
- 11 int num2 = 5;
- // 查看num1的值
- (gdb) print num1
- $1 = 3
- // 查看num1的地址
- (gdb) print &num1
- $2 = (int *) 0x7fffffffe2c4
复制代码 gdb 小技巧
shell
gdb 可以执行 shell 命令。请看示例:
[code]Type "apropos word" to search for commands related to "word"...Reading symbols from demo2...// ll 命令没有(gdb) shell llbash: ll:未找到命令// 执行 ls 命令(gdb) shell lsdemo2 demo2.c// 执行 cat 命令(gdb) shell cat demo2.c#include int main() { int i; for (i = 1; i |