前端学习 C 语言 —— GDB调试器

打印 上一主题 下一主题

主题 883|帖子 883|积分 2649

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:
  1. jjj-pc:~/pj/glmark2$ sudo apt install gdb
  2. 正在读取软件包列表... 完成
  3. 正在分析软件包的依赖关系树
  4. 正在读取状态信息... 完成
  5. gdb 已经是最新版 (9.1-0kylin1)。
  6. 下列软件包是自动安装的并且现在不需要了:
  7.   archdetect-deb dmeventd libaio1 libdebian-installer4 libdevmapper-event1.02.1 liblvm2cmd2.03 localechooser-data lvm2 user-setup
  8. 使用'sudo apt autoremove'来卸载它(它们)。
  9. 升级了 0 个软件包,新安装了 0 个软件包,要卸载 0 个软件包,有 6 个软件包未被升级。
复制代码
笔者gbd版本是 9.1
  1. jjj-pc:~/pj/glmark2$ gdb --version
  2. GNU gdb (Ubuntu 9.1-0kylin1) 9.1
  3. Copyright (C) 2020 Free Software Foundation, Inc.
  4. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  5. This is free software: you are free to change and redistribute it.
  6. There is NO WARRANTY, to the extent permitted by law.
复制代码
最常用命令

man gdb 告诉我们最常用的命令有:break、run、print、c、next、list、step、quit。
  1. // 以下是一些最常用的GDB命令:
  2. Here are some of the most frequently needed GDB commands:
  3.        break [file:]function
  4.            Set a breakpoint at function (in file).
  5.        run [arglist]
  6.            Start your program (with arglist, if specified).
  7.        bt  Backtrace: display the program stack.
  8.        print expr
  9.            // 显示表达式的值
  10.            Display the value of an expression.
  11.        c   Continue running your program (after stopping, e.g. at a breakpoint).
  12.        next
  13.            // 执行下一条程序语句(在停止后);跳过该行中的任何函数调用。
  14.            Execute next program line (after stopping); step over any function calls in the line.
  15.        edit [file:]function
  16.            look at the program line where it is presently stopped.
  17.        list [file:]function
  18.            type the text of the program in the vicinity of where it is presently stopped.
  19.        step
  20.            Execute next program line (after stopping); step into any function calls in the line.
  21.        help [name]
  22.            Show information about GDB command name, or general information about using GDB.
  23.        quit
  24.            Exit from GDB.
复制代码
准备一段 C 代码用作gdb命令学习:
  1. #include <stdio.h>
  2. // add 函数
  3. int add(int a, int b) {
  4.     int sum = a + b;
  5.     return sum;
  6. }
  7. int main() {
  8.     int num1 = 3;
  9.     int num2 = 5;
  10.    
  11.     int result = add(num1, num2);
  12.    
  13.     printf("两个整数的和为:%d\n", result);
  14.    
  15.     return 0;
  16. }
复制代码
run 和 quit

通过 gdb demo 运行进入gdb模式,输入 run 运行程序,输入 quit 则退出gdb。详细请看:
  1. // 通过 -g 编译出有调试信息的可执行文件
  2. jjj-pc:~/pj$ gcc demo.c -o demo -g
  3. // gdb 运行
  4. jjj-pc:~/pj$ gdb demo
  5. GNU gdb (Ubuntu 9.1-0kylin1) 9.1
  6. Copyright (C) 2020 Free Software Foundation, Inc.
  7. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  8. This is free software: you are free to change and redistribute it.
  9. There is NO WARRANTY, to the extent permitted by law.
  10. Type "show copying" and "show warranty" for details.
  11. This GDB was configured as "x86_64-linux-gnu".
  12. Type "show configuration" for configuration details.
  13. For bug reporting instructions, please see:
  14. <http://www.gnu.org/software/gdb/bugs/>.
  15. Find the GDB manual and other documentation resources online at:
  16.     <http://www.gnu.org/software/gdb/documentation/>.
  17. For help, type "help".
  18. Type "apropos word" to search for commands related to "word"...
  19. Reading symbols from demo...
  20. // 输入 run 运行程序
  21. (gdb) run
  22. Starting program: /home/jjj/pj/demo
  23. 两个整数的和为:8
  24. [Inferior 1 (process 3022770) exited normally]
  25. // 输入 quit 退出
  26. (gdb) quit
  27. jjj-pc:~/pj$
复制代码
Tip: ctrl + z 能直接退出gdb
list

如果不知道在哪行或哪个方法打断点,可以通过 list 查看源码。请看示例:
  1. jjj-pc:~/pj$ gdb demo
  2. GNU gdb (Ubuntu 9.1-0kylin1) 9.1
  3. Copyright (C) 2020 Free Software Foundation, Inc.
  4. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  5. This is free software: you are free to change and redistribute it.
  6. There is NO WARRANTY, to the extent permitted by law.
  7. Type "show copying" and "show warranty" for details.
  8. This GDB was configured as "x86_64-linux-gnu".
  9. Type "show configuration" for configuration details.
  10. For bug reporting instructions, please see:
  11. <http://www.gnu.org/software/gdb/bugs/>.
  12. Find the GDB manual and other documentation resources online at:
  13.     <http://www.gnu.org/software/gdb/documentation/>.
  14. For help, type "help".
  15. Type "apropos word" to search for commands related to "word"...
  16. Reading symbols from demo...
  17. // 查看源码
  18. (gdb) list
  19. 1       #include <stdio.h>
  20. 2
  21. 3       // 自定义函数,用于计算两个整数的和
  22. 4       int add(int a, int b) { // a, b 叫形参
  23. 5           int sum = a + b;
  24. 6           return sum;
  25. 7       }
  26. 8
  27. 9       int main() {
  28. 10          int num1 = 3;
  29. // 一次显示不完,继续查看后面10行
  30. (gdb) list
  31. 11          int num2 = 5;
  32. 12
  33. 13          // 调用自定义函数计算两个整数的和
  34. 14          int result = add(num1, num2);
  35. 15
  36. 16          printf("两个整数的和为:%d\n", result);
  37. 17
  38. 18          return 0;
  39. 19      }
  40. // 到底了。
  41. (gdb) list
  42. Line number 20 out of range; demo.c has 19 lines.
  43. // 查看5到10行
  44. (gdb) list 5,10
  45. 5           int sum = a + b;
  46. 6           return sum;
  47. 7       }
  48. 8
  49. 9       int main() {
  50. 10          int num1 = 3;
  51. (gdb)
复制代码
break 和 info break

break(简写 b) 用于打断点,info break 用于查看打了哪些断点。请看示例:
  1. jjj-pc:~/pj$ gdb demo
  2. GNU gdb (Ubuntu 9.1-0kylin1) 9.1
  3. Copyright (C) 2020 Free Software Foundation, Inc.
  4. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  5. This is free software: you are free to change and redistribute it.
  6. There is NO WARRANTY, to the extent permitted by law.
  7. Type "show copying" and "show warranty" for details.
  8. This GDB was configured as "x86_64-linux-gnu".
  9. Type "show configuration" for configuration details.
  10. For bug reporting instructions, please see:
  11. <http://www.gnu.org/software/gdb/bugs/>.
  12. Find the GDB manual and other documentation resources online at:
  13.     <http://www.gnu.org/software/gdb/documentation/>.
  14. For help, type "help".
  15. Type "apropos word" to search for commands related to "word"...
  16. Reading symbols from demo...
  17. // 给 mian 方法打断点
  18. (gdb) break main
  19. Breakpoint 1 at 0x1167: file demo.c, line 9.
  20. // 给11行打断点
  21. (gdb) b 11
  22. Breakpoint 2 at 0x117a: file demo.c, line 11.
  23. // 查看打了哪些断点
  24. (gdb) info b
  25. Num     Type           Disp Enb Address            What
  26. 1       breakpoint     keep y   0x0000000000001167 in main at demo.c:9
  27. 2       breakpoint     keep y   0x000000000000117a in main at demo.c:11
  28. // 查看打了哪些断点
  29. (gdb) info break
  30. Num     Type           Disp Enb Address            What
  31. 1       breakpoint     keep y   0x0000000000001167 in main at demo.c:9
  32. 2       breakpoint     keep y   0x000000000000117a in main at demo.c:11
复制代码
next 和 step

代码中断后,输入 next 和 step 都会执行下一行,然而 next 会跳过函数,step 会进入函数。请看示例:

  • next 跳过函数
  1. Type "apropos word" to search for commands related to "word"...
  2. Reading symbols from demo...
  3. // 打断点
  4. (gdb) b 9
  5. Breakpoint 1 at 0x1167: file demo.c, line 9.
  6. // 运行
  7. (gdb) run
  8. Starting program: /home/jjj/pj/demo
  9. // 在断点处停止
  10. Breakpoint 1, main () at demo.c:9
  11. 9       int main() {
  12. // 下一行
  13. (gdb) next
  14. 10          int num1 = 3;
  15. (gdb) next
  16. // 下一行
  17. 11          int num2 = 5;
  18. (gdb) next
  19. // 下一行。跳过函数
  20. 14          int result = add(num1, num2);
  21. (gdb) next
  22. // 下一行
  23. 16          printf("两个整数的和为:%d\n", result);
  24. (gdb) next
  25. 两个整数的和为:8
  26. 18          return 0;
复制代码

  • step 进入函数
  1. Type "apropos word" to search for commands related to "word"...
  2. Reading symbols from demo...
  3. (gdb) b 9
  4. Breakpoint 1 at 0x1167: file demo.c, line 9.
  5. (gdb) run
  6. Starting program: /home/jjj/pj/demo
  7. Breakpoint 1, main () at demo.c:9
  8. 9       int main() {
  9. (gdb) step
  10. 10          int num1 = 3;
  11. (gdb) step
  12. 11          int num2 = 5;
  13. (gdb) step
  14. 14          int result = add(num1, num2);
  15. (gdb) step
  16. add (a=21845, b=1431654909) at demo.c:4
  17. 4       int add(int a, int b) {
  18. (gdb) step
  19. 5           int sum = a + b;
  20. (gdb) step
  21. 6           return sum;
  22. (gdb) step
  23. 7       }
  24. (gdb) step
  25. main () at demo.c:16
  26. 16          printf("两个整数的和为:%d\n", result);
  27. (gdb) step
  28. 两个整数的和为:8
  29. 18          return 0;
复制代码
continue

next 和 step 会执行下一行,而continue(简写c) 会执行到下一个断点处停止。 请看示例:
  1. Type "apropos word" to search for commands related to "word"...
  2. Reading symbols from demo...
  3. // 断点
  4. (gdb) b main
  5. Breakpoint 1 at 0x1167: file demo.c, line 9.
  6. // 断点
  7. (gdb) b 16
  8. Breakpoint 2 at 0x1193: file demo.c, line 16.
  9. // 运行后在第一断点处停止
  10. (gdb) run
  11. Starting program: /home/jjj/pj/demo
  12. Breakpoint 1, main () at demo.c:9
  13. 9       int main() {
  14. // 下一个断点
  15. (gdb) c
  16. Continuing.
  17. Breakpoint 2, main () at demo.c:16
  18. 16          printf("两个整数的和为:%d\n", result);
  19. (gdb)
复制代码
print

print 用于查看表达式的值。请看示例:
  1. // 在11行打断点,查看 num1
  2. (gdb) list 9,11
  3. 9       int main() {
  4. 10          int num1 = 3;
  5. 11          int num2 = 5;
  6. (gdb) b 11
  7. Breakpoint 1 at 0x117a: file demo.c, line 11.
  8. (gdb) run
  9. Starting program: /home/jjj/pj/demo
  10. Breakpoint 1, main () at demo.c:11
  11. 11          int num2 = 5;
  12. // 查看num1的值
  13. (gdb) print num1
  14. $1 = 3
  15. // 查看num1的地址
  16. (gdb) print &num1
  17. $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
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

莱莱

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表