gdb 素颜马尾好姑娘i 2022-08-10 03:43 504阅读 0赞 本文介绍Linux下GDB调试器常用的基本命令。 测试均在Ubuntu12.10下完成。 先看看GDB调试的效果图: ![20130522144628921][] 对应的源代码: **\[cpp\]** [view plain][] [copy][view plain] [print][view plain] [?][view plain] 1. //插入排序,GDB调试测试代码 2. \#include <stdio.h> 3. 4. **int** x\[10\],//存放输入数据 5. y\[10\],//工作空间数组 6. num\_inputs,//输入数组长度 7. num\_y = 0;//y中当前元素个数 8. 9. //函数 10. //功能:从参数中提取输入数据 11. **void** get\_args(**int** ac,**char** \*\*av)\{ 12. **int** i; 13. num\_inputs = ac - 1; 14. **for**(i = 0;i < num\_inputs;++i) 15. x\[i\] = atoi(av\[i + 1\]); 16. \} 17. 18. //函数 19. //功能:向右移动工作数组中索引jj及其后面的所有元素 20. **void** scoot\_over(**int** jj)\{ 21. **int** k; 22. **for**(k = num\_y;k > jj;++k) 23. y\[k\] = y\[k - 1\]; 24. \} 25. 26. //函数: 27. //功能:插入一个数据 28. **void** insert(**int** new\_y)\{ 29. **int** j; 30. //工作数组为空 31. **if**(0 == num\_y)\{ 32. y\[0\] = new\_y; 33. **return**; 34. \} 35. 36. //将新元素插入到适当位置:第一个比new\_y大的元素前面 37. **for**(j = 0;j < num\_y;++j)\{ 38. **if**(new\_y < y\[j\])\{ 39. //向右移动y\[j\]后面的所有元素 40. scoot\_over(j); 41. y\[j\] = new\_y; 42. **return**; 43. \} 44. \} 45. \} 46. 47. //函数: 48. //功能:处理所有输入数据 49. **void** process\_data()\{ 50. **for**(num\_y = 0;num\_y < num\_inputs;++num\_y) 51. insert(x\[num\_y\]); 52. \} 53. 54. //函数: 55. //打印结果数据 56. **void** print\_results()\{ 57. **int** i; 58. **for**(i = 0;i < num\_inputs;++i) 59. printf("%d\\n",y\[i\]); 60. \} 61. 62. **int** main(**int** argc,**char** \*\*argv)\{ 63. get\_args(argc,argv); 64. process\_data(); 65. print\_results(); 66. \} 源代码编译: gcc -g -Wall -o insert\_sort ins.c 这里面一个必要的步骤是:GCC的-g选项:让编译器将符号表(对应于程序的变量和代码行的内存地址列表)保存在生成的可执行文件中。这样才能在调试会话过程中引用源代码中的变量名和行号。 一些基本命令 启动GDB:gdb exeFileName gdb中中文显示是乱码,暂时还不知道怎么支持中文。 联机帮助,可以通过help命令访问文档:(gdb) help breakpoints 以TUI模式运行GDB:在调用gdb的时候指定-tui选项或者在处于非TUI模式时在GDB中使用Ctrl+X+A组合键,可以将终端屏幕分成原文本窗口和控制台的多个子窗口 退出GDB:quit或者Ctrl+d 可以直接按下回车再次执行最近执行过的那条命令 执行程序:run 查看栈帧:frame num(栈帧编号) 注意栈帧编号规则,当前正在执行的函数的帧被编号为0,其父帧(即该函数的调用者的栈帧)被编号为1,父帧的父帧被编号为2,以此类推。 跳到调用栈中的下一个父帧:up 引向相反方向:down 显示整个栈,即当前存在的所有帧的集合:backtrace 滚动查看代码:↑等箭头键 输出当前值:print或者p 浏览以前的GDB命令:上一个Ctrl+P、下一个Ctrl+N 注意:如果我们需要修改程序,并且重新编译,不必重启GDB。GDB会在运行程序之前自动重新加载新的二分表和新的符号表。 我们在重新编译程序之前仍然不必退出GDB。 断点相关操作 设置断点 GDB设置点的后,该断点的有效性会持续到删除、禁用或退出GDB时。 在某一行设置断点:break line\_number(行数) break filename:line\_number 在源代码文件filename的line\_number处设置断点。 在某个函数的入口(第一行可执行代码)处设置断点:break function(函数名)。这种方法相对以行数设置断点有一个优点:如果修改了源代码,使得函数不再在这一行处开始,那么如果用函数名指定断点,而不是用行号指定,则断点仍然有效。 注意:break function会在所有具有相同名称的函数上设置断点,注意函数重载的情况。 break filename: function 在源代码文件filename的函数function入口处处设置断点。 当GDB使用多个断点中断一行源代码时,它只会中断一次。 GDB实际设置断点的位置可能和我们请求将断点放置的位置不同。 比如下列代码: **\[cpp\]** [view plain][] [copy][view plain] [print][view plain] [?][view plain] 1. **int** main(**void**) 2. \{ 3. **int** i; 4. i = 3; 5. 6. **return** 0; 7. \} 如果我们尝试在函数main入口处设置断点,断点实际会被设置在第4行。因为GDB会认为第三行的机器码对我们的调试目的来说没有用处。 条件断点 将正常断点转变为条件断点:condition break\_p\_num(断点编号) cond(条件) 在有效的C条件语句中几乎可以用任何表达式。也可以用自己的函数或者库函数,只要他们被链接到程序中。 如:condition 1 num\_y == 1 只有当满足条件num\_y == 1时,GDB才会在断点1处暂停程序的执行。 如果以后要删除条件,但是保持断点,只需键入:cond break\_p\_num(断点编号) 用break if可以将break和condition命令组合成一个步骤: break line\_num(行号) if cond(条件) 例子:(gdb) nreak 30 if num\_y == 1 注意,条件语句可以用括号()括起来,也可以不用。 临时断点:tbreak 与break类似,但是这一命令设置的断点在首次到达该指定行后就不再有效。 删除断点 **基于标识符删除断点:delete** delete break\_point\_num(断点编号),可以在后面指定多个断点编号连续删除几个断点 delete:删除所有断点 **另一种删除断点方式:clear** 依据位置删除断点,工作方式和对应的break命令相似: clear function clear filename:funtion clear line\_number clear filename:line\_number clear:清除GDB将执行的下一个指令处的断点 禁用与启用断点 禁用断点:disable breakpoint-list(是用空格分隔开的多个断点标识符) 禁用所有现存断点:disable 启用断点:enable breakpoint-list 在下次引起GDB暂停执行后禁用:enable once breakpoint-list 查看所有断点信息:info break或者是info breakpoints或者简写为i b 断点命令列表 让GDB在每次到达某个断点时自动执行一组命令,从而自动完成某一任务。 使用commands命令设置命令列表: commands breakpoint\_number ... commands ... end 例如以下代码: ![20130522144849323][] 我打算查看传递给fibonacci函数的值以及次序,但是不想在程序中插入printf语句并重新编译代码,可以这样做: 在该函数入口处设置一个断点,然后设置命令列表: ![20130522144914759][] printf命令和C中printf函数类似,只是括号是可选的。 运行结果: ![20130522144941649][] 如果嫌GDB输出太冗长,可以使用silent命令,只需将其添加到设置的命令列表最开始处即可。 ![20130522145006586][] 恢复执行 三种方法 (1)单步执行:step(s)、next(n),仅执行到代码的下一行后再次暂停。 注意二者区别:在函数调用时step会进入函数,next导致下一次暂停出现在调用函数之后。next被称为单步越过(stepping over)函数,而step被称为单步进入(stepping into)函数。 next和step都可以采用一个可选的数值参数,来表示要使用next或step执行的额外行数。 (2)无条件恢复程序的执行:continue(c) 直到遇到另一个断点或者程序结束。 continue可以接受一个可选的数值参数n,要求GDB忽略下面n个断点。 (3)用finish(fin)或until(u)命令恢复。 finish命令指示GDB恢复执行,直到恰好在当前帧完成之后为止。 until命令通常用来在不进一步在循环中暂停(除了循环中的中间断点)的情况下完成正在执行的循环。until会执行循环的其余部分(如果遇到断点,还是会暂停),让GDB在循环后面的第一行代码处暂停。 until命令也可以接受源代码中的位置作为参数,其用法与break命令同。 比如下列代码清单swapflaw.c: **\[cpp\]** [view plain][] [copy][view plain] [print][view plain] [?][view plain] 1. \#include <stdio.h> 2. 3. **void** swap(**int** \*a,**int** \*b)\{ 4. **int** c = \*a; 5. \*a = \*b; 6. \*b = c; 7. \} 8. 9. **int** main(**void**)\{ 10. **int** i = 3; 11. **int** j = 5; 12. 13. printf("i:%d,j:%d\\n",i,j); 14. swap(&i,&j); 15. printf("i:%d,j:%d\\n",i,j); 16. 17. **return** 0; 18. \} 如果GDB触发了main函数入口处的一个断点,那么可以使用下面这些命令方便地使程序一直执行到swap()的入口: until 13 until swap until swapflaw.c:13 until swapflaw.c:swap 监视点 监视点是一种特殊类型的断点,区别在于监视点没有“住在”某一行源代码中,而是指示GDB每当某个表达式改变了值就暂停执行。 设置监视点:watch z(变量名)也可以是复杂的表达式 注意只能监视存在且在作用域内的变量。一旦变量不再存在调用栈的任何帧中,GDB会自动删除监视点。 GDB实际上是在变量的内存位置改变值时中断。 文件清单 (gdb) list line1,line2 查看源代码 list lineNum 在lineNum的前后源代码显示出来 list + 列出当前行的后面代码行 list - 列出当前行的前面代码行 list function set listsize count 设置显示代码的行数 show listsize 显示打印代码的行数 list first,last 显示从first到last的源代码行 **GDB启动文件的使用** 有时候我们在完成调试前可能需要退出GDB,比如需要离开比较长的一段时间而且不能保持登录在计算机中。为了不丢失某些信息,可以将断点和设置的其他命令放在一个GDB启动文件中,然后每次启动GDB时会自动加载它们。 GDB启动文件默认名为.gdbinit。可以将一个文件放在主目录中用于一般用途,另一个文件放在特定项目专用的目录中。例如,可以将设置断点的命令放在后一个目录的启动文件中,在主目录的.gdbinit文件中存储开发的一些通用的宏。最好不要将编程项目放在主目录中,因为不能将项目特有的信息放在.gdbinit中。 在调用GDB时可以指定启动文件,如: $gdb -command=z x 表示要在可执行文件x上运行GDB,首先要从文件z中读取命令。 [20130522144628921]: /images/20220731/362fb13875544af48bb0a4584a86425d.png [view plain]: http://blog.csdn.net/xiajun07061225/article/details/8960332# [20130522144849323]: /images/20220731/ff8a908a30c24936add8435553074a6d.png [20130522144914759]: /images/20220731/5b3862c279da4839a2f38c68692c8d2b.png [20130522144941649]: /images/20220731/1ef28ae49b814931862484903b328ab4.png [20130522145006586]: /images/20220731/814a3935cb8341fda185b7daa3050e46.png
相关 gdb `backtrace(简写为bt`命令查看函数调用的栈帧: `nfo(简写为i)`查看函数中局部变量的值: i locals 查看函数当前局部变量的值用`frame(简写为 向右看齐/ 2023年08月17日 17:37/ 0 赞/ 113 阅读
相关 gdb命令 g++ 简单编译指令 > g++ -g -std=c++11 main.cpp -o main.out > gdb main.out 常用的指令如下: 指令中 清疚/ 2022年11月12日 04:12/ 0 赞/ 250 阅读
相关 GDB学习 链接: http://wiki.ubuntu.com.cn/index.php?title=%E7%94%A8GDB%E8%B0%83%E8%AF%95%E7%A8 朱雀/ 2022年08月22日 05:58/ 0 赞/ 79 阅读
相关 gdb 本文介绍Linux下GDB调试器常用的基本命令。 测试均在Ubuntu12.10下完成。 先看看GDB调试的效果图: ![20130522144628921][] 素颜马尾好姑娘i/ 2022年08月10日 03:43/ 0 赞/ 505 阅读
相关 gdb 调试 基本用法 1. gcc -g xx.c xx 2. gdb xx 基本命令 1. start 启动程序, 默认停留在main程序的第一行 2. run 启 刺骨的言语ヽ痛彻心扉/ 2022年06月09日 11:26/ 0 赞/ 362 阅读
相关 GDB gdb调试命令的使用及总结 作者: 字体:\[增加 减小\] 类型:转载 时间:2013-05-04[ 我要评论][Link 1] gdb是一个在UNIX环境下的命令行 分手后的思念是犯贱/ 2022年06月07日 06:29/ 0 赞/ 222 阅读
相关 gdb调试 在用gcc编程的时候可能会出bug,这时候就可以通过gdb这个工具进行调试,gdb调试的一定是直接有\.c 文件生成的bebug版本的可执行文件,否则,进入gdb之后敲入lis Dear 丶/ 2022年06月02日 07:55/ 0 赞/ 411 阅读
相关 GDB使用 参考出处: https://www.ibm.com/developerworks/cn/linux/sdk/gdb/index.html 摘要 gdb 目标文件 run 迈不过友情╰/ 2022年05月26日 05:19/ 0 赞/ 281 阅读
相关 interpret of gdb "gdb info reg" (gdb) info reg eax 0x0 0 ecx 0x0 0 edx 0xff 我就是我/ 2022年05月26日 04:24/ 0 赞/ 224 阅读
相关 GDB调试 另外有: Gdb+core调试技术 http://zhwen.org/xlog/?p=453 一、gdb简介和安装 GDB是GNU开源组织发 谁践踏了优雅/ 2022年01月22日 04:29/ 0 赞/ 411 阅读
还没有评论,来说两句吧...