> 技术文档 > Linux调试器gdb和cgdb的使用【Ubuntu】_no source available for "(gdb[24].proc[42000].thre

Linux调试器gdb和cgdb的使用【Ubuntu】_no source available for "(gdb[24].proc[42000].thre


文章目录

  • 一、样例代码
  • 二、预备
  • 三、常见使用
    • 1、cgdb调试操作
    • 2、gdb调试操作
  • 四、常见技巧
    • 1、 **安装cgdb:**
    • 2、watch
    • 3、set var确定问题原因
    • 4、条件断点

一、样例代码

// mycmd.c#include int Sum(int s, int e){int result = 0;for(int i = s; i <= e; i++){result += i;} return result;} int main(){int start = 1;int end = 100;printf(\"I will begin\\n\");int n = Sum(start, end);printf(\"running done, result is: [%d-%d]=%d\\n\", start, end, n);return 0;}

二、预备

• 程序的发布方式有两种, debug 模式和 release 模式, Linux gcc/g++ 出来的二进制程序,默认是 release 模式。
• 要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项,如果没有添加,程序无法被编译

$ gcc mycmd.c -o mycmd # 默认模式,不支持调试$ file mycmd mycmd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=82f5cbaada10a9987d9f325384861a88d278b160, for GNU/Linux 3.2.0, not stripped$ gcc mycmd.c -o mycmd -g # debug模式$ file mycmdmycmd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2,BuildID[sha1]=3d5a2317809ef86c7827e9199cfefa622e3c187f, for GNU/Linux 3.2.0, with debug_info, not stripped

三、常见使用

  • 开始gdb binFile
  • 退出ctrl + dquit 调试命令

1、cgdb调试操作

按下ESC键进入代码窗口,此时可以上下浏览代码,并且可以进行一系列的操作:

按键 操作 空格键 设置或者取消断点; o 查看代码所在的文件; / 或者 ? 在代码中搜索字符串; - 缩小代码窗口; + 扩大代码窗口; gg 光标移动到文件头部; GG 光标移动到文件尾部; ctrl + b 代码向上翻一页; ctrl + u 代码向上翻半页; ctrl + f 代码向下翻一页; ctrl + d 代码向下翻半页;

按下i键回到调试窗口,进入调试模式,使用的调试指令与GDB几乎一样!

2、gdb调试操作

命令 作用 样例 list/l 显⽰源代码,从上次位置开始,每次列出 list/l 10 list/l 函数名 列出指定函数的源代码 list/l main list/l ⽂件名:行号 列出指定⽂件的源代码 list/l mycmd.c:1 r/run 从程序开始连续执⾏ run n/next 单步执行,不进⼊函数内部 next s/step 单步执行,进⼊函数内部 step break/b [⽂件名:]行号 在指定⾏号设置断点 break 10 break test.c:10 break/b 函数名 在函数开头设置断点 break main info break/b 查看当前所有断点的信息 info break finish 执⾏到当前函数返回,然后停⽌ finish print/p 表达式 打印表达式的值 print start+end p 变量 打印指定变量的值 p x set var 变量=值 修改变量的值 set var i=10 continue/c 从当前位置开始连续执⾏程序 continue delete/d breakpoints 删除所有断点 delete breakpoints delete/d breakpoints n 删除序号为n的断点 delete breakpoints 1 disable breakpoints 禁⽤所有断点 disable breakpoints enable breakpoints 启⽤所有断点 enable breakpoints info/i breakpoints 查看当前设置的断点列表 info breakpoints display 变量名 跟踪显⽰指定变量的值(每次停止时) display x undisplay 编号 取消对指定编号的变量的跟踪显示 undisplay 1 until X⾏号 执⾏到指定⾏号 until 20 backtrace/bt 查看当前执⾏栈的各级函数调⽤及参数 backtrace info/i locals 查看当前栈帧的局部变量值 info locals quit 退出GDB调试器 quit
  • -断点(breakpoints) -行号(n)

四、常见技巧

📌

1、 安装cgdb:

• 上面的基本调试还是麻烦,虽然是黑屏,但是还是想看到代码调试
推荐安装cgdb:
• Ubuntu: sudo apt-get install -y cgdb
• Centos: sudo yum install -y cgdb

2、watch

执行时监视一个表达式(如变量)的值。如果监视的表达式在程序运行期间的值发生变化,GDB 会暂
停程序的执行,并通知使用者

(gdb) l main1112 return result;13 }1415 int main()16 {17 int start = 1;18 int end = 100;19 printf(\"I will begin\\n\");20 int n = Sum(start, end);(gdb) b 20Breakpoint 1 at 0x11c3: file mycmd.c, line 20.(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x00000000000011c3 in main at mycmd.c:20 (gdb) rStarting program: /home/whb/test/test/mycmdI will beginBreakpoint 1, main () at mycmd.c:2020 int n = Sum(start, end);(gdb) sSum (s=32767, e=-7136) at mycmd.c:55 {(gdb) n6 int result = 0;(gdb) watch resultHardware watchpoint 2: result(gdb) cContinuing.Hardware watchpoint 2: resultOld value = -6896New value = 0Sum (s=1, e=100) at mycmd.c:77 for(int i = s; i <= e; i++)(gdb) cContinuing.Hardware watchpoint 2: resultOld value = 0New value = 1Sum (s=1, e=100) at mycmd.c:77 for(int i = s; i <= e; i++)(gdb) cContinuing.Hardware watchpoint 2: resultOld value = 1New value = 3Sum (s=1, e=100) at mycmd.c:77 for(int i = s; i <= e; i++)(gdb) cContinuing.Hardware watchpoint 2: resultOld value = 3New value = 6Sum (s=1, e=100) at mycmd.c:77 for(int i = s; i <= e; i++)(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20breakpoint already hit 1 time2 hw watchpoint keep y resultbreakpoint already hit 4 times(gdb) d 2(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20breakpoint already hit 1 time(gdb) finishRun till exit from #0 Sum (s=1, e=100) at mycmd.c:70x00005555555551d2 in main () at mycmd.c:2020 int n = Sum(start, end);Value returned is $1 = 5050

📌 注意:

  • 如果你有一些变量不应该修改,但是你怀疑它修改导致了问题,你可以watch它,如果变
    化了,就会通知你.

3、set var确定问题原因

更改一下标志位,假设我们想得到 +-result

// mycmd.c#include int flag = 0; // 故意错误//int flag = -1;//int flag = 1;int Sum(int s, int e){int result = 0;for(int i = s; i <= e; i++){result += i;}return result*flag;} int main(){int start = 1;int end = 100;printf(\"I will begin\\n\");int n = Sum(start, end);printf(\"running done, result is: [%d-%d]=%d\\n\", start, end, n);return 0;}(gdb) l main1516return result*flag;17 }1819 int main()20 {21 int start = 1;22 int end = 100;23 printf(\"I will begin\\n\");24 int n = Sum(start, end);(gdb) b 24Breakpoint 1 at 0x11ca: file mycmd.c, line 24.(gdb) rStarting program: /home/whb/test/test/mycmdI will beginBreakpoint 1, main () at mycmd.c:2424 int n = Sum(start, end);(gdb) n25 printf(\"running done, result is: [%d-%d]=%d\\n\", start, end,n);(gdb) nrunning done, result is: [1-100]=0 # 这⾥结果为什么是026 return 0;(gdb) rThe program being debugged has been started already.Start it from the beginning? (y or n) yStarting program: /home/whb/test/test/mycmdI will beginBreakpoint 1, main () at mycmd.c:2424 int n = Sum(start, end);(gdb) sSum (s=32767, e=-7136) at mycmd.c:99 {(gdb) n10 int result = 0;(gdb) n11 for(int i = s; i <= e; i++)(gdb)13 result += i;(gdb)11 for(int i = s; i <= e; i++)(gdb)13 result += i;(gdb) until 14Sum (s=1, e=100) at mycmd.c:1616 return result*flag;(gdb) p result$1 = 5050(gdb) p flag$2 = 0(gdb) set var flag=1 # 更改flag的值,确认是否是它的原因(gdb) p flag$3 = 1(gdb) n17 }(gdb) nmain () at mycmd.c:2525 printf(\"running done, result is: [%d-%d]=%d\\n\", start, end,n);(gdb) nrunning done, result is: [1-100]=5050 # 是它的原因26 return 0;

4、条件断点

添加条件断点

(gdb) l main1112 return result;13 }1415 int main()16 {17 int start = 1;18 int end = 100;19 printf(\"I will begin\\n\");20 int n = Sum(start, end);(gdb) b 20Breakpoint 1 at 0x11c3: file mycmd.c, line 20.(gdb) rStarting program: /home/whb/test/test/mycmdI will beginBreakpoint 1, main () at mycmd.c:2020 int n = Sum(start, end);(gdb) sSum (s=32767, e=-7136) at mycmd.c:55 {(gdb) n6 int result = 0;(gdb) n7 for(int i = s; i <= e; i++)(gdb) n9 result += i;(gdb) display i1: i = 1(gdb) n7 for(int i = s; i <= e; i++)1: i = 1(gdb) n9 result += i;1: i = 2(gdb) n7 for(int i = s; i <= e; i++)1: i = 2(gdb) n9 result += i;1: i = 3(gdb)7 for(int i = s; i <= e; i++)1: i = 3(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20breakpoint already hit 1 time(gdb) b 9 if i == 30 # 9是⾏号,表⽰新增断点的位置Breakpoint 2 at 0x555555555186: file mycmd.c, line 9.(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20breakpoint already hit 1 time2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9stop only if i == 30(gdb) finishRun till exit from #0 Sum (s=1, e=100) at mycmd.c:7Breakpoint 2, Sum (s=1, e=100) at mycmd.c:99 result += i;1: i = 30(gdb) finishRun till exit from #0 Sum (s=1, e=100) at mycmd.c:90x00005555555551d2 in main () at mycmd.c:2020 int n = Sum(start, end);Value returned is $1 = 5050

给已经存在的端点新增条件

(gdb) l main1112 return result;13 }1415 int main()16 {17 int start = 1;18 int end = 100;19 printf(\"I will begin\\n\");20 int n = Sum(start, end);(gdb) b 20Breakpoint 1 at 0x11c3: file mycmd.c, line 20.(gdb) rStarting program: /home/whb/test/test/mycmdI will beginBreakpoint 1, main () at mycmd.c:2020 int n = Sum(start, end);(gdb) sSum (s=32767, e=-7136) at mycmd.c:55 {(gdb) n6 int result = 0;(gdb) n7 for(int i = s; i <= e; i++)(gdb) n9 result += i;(gdb)7 for(int i = s; i <= e; i++)(gdb)9 result += i;(gdb)7 for(int i = s; i <= e; i++)(gdb)9 result += i;(gdb)7 for(int i = s; i <= e; i++)(gdb) b 9 # 我们在第9⾏新增⼀个断点,⽤来开始测试Breakpoint 2 at 0x555555555186: file mycmd.c, line 9.(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20breakpoint already hit 1 time2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9(gdb) nBreakpoint 2, Sum (s=1, e=100) at mycmd.c:99 result += i;(gdb) n7 for(int i = s; i <= e; i++)(gdb) nBreakpoint 2, Sum (s=1, e=100) at mycmd.c:99 result += i;(gdb) condition 2 i==30 #给2号断点,新增条件i==30(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20breakpoint already hit 1 time2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9stop only if i==30breakpoint already hit 2 times(gdb) n7 for(int i = s; i <= e; i++)(gdb) n9 result += i;(gdb) cContinuing.Breakpoint 2, Sum (s=1, e=100) at mycmd.c:99 result += i;(gdb) p i$1 = 30(gdb) p result$2 = 435

📌 注意:

  • 条件断点添加常见两种方式:1. 新增 2. 给已有断点追加
  • 注意两者的语法有区别,不要写错了。
  • 新增: b 行号/文件名:行号/函数名 if i == 30(条件)
  • 给已有断点追加:condition 2 i==30, 其中2是已有断点编号,没有if