Linux开发工具(gdb/cgdb篇)
目录1.模式-g选项让最后形成的可执行程序添加调试信息---dabug模式程序要调试必须debug模式也就是说明编译时要加-g选项2.安装gdb3.快速认识gdb输入quit可以退出 查看代码list b打 断点 r运行 c运行结束4.解决一些gdb难用的问题cgdb5.gdb/cgdb命令常见使用1.b 打断点 b 行号 info b查看断点 d 断点编号 删除断点 r运行程序gdb不退出断点变化依次递增n和s bt查看当前函数栈帧 finish执行到当前函数返回调试的本质是什么6.三个debug技巧1.模式软件开发发布的模式有两种1.debug模式2.release模式debug一般是开发期间使用的release一般是发布期间用的---测试---上线Windows下我们编译好程序可以直接调试linux下下载我们编程好的代码无法直接调试gcc/g默认的工作模式是release模式-g选项让最后形成的可执行程序添加调试信息---dabug模式程序要调试必须debug模式也就是说明编译时要加-g选项在Makefile里面加个-g1 SRC$(wildcard *.c) 2 OBJ$(SRC:.c.o) 3 BINprocessbar 4 5 $(BIN):$(OBJ) 6 gcc -o $ $^ 7 %.o:%.c 8 gcc -c $ -stdc99 -g 9 10 .PHONY: 11 clean: 12 rm -f $(OBJ) $(BIN)[user1iZ5waahoxw3q2bZ processbar]$ make gcc -c main.c -stdc99 -g gcc -c process.c -stdc99 -g gcc -o processbar main.o process.o原来make之后的processbar-rwxrwxr-x 1 user1 user1 9024 Apr 16 13:32 processbar之后的-rwxrwxr-x 1 user1 user1 12576 Apr 16 15:16 processbar明显发现体积增大了可以发现多了好几个debug[user1iZ5waahoxw3q2bZ processbar]$ readelf -S processbar | grep -i debug [28] .debug_aranges PROGBITS 0000000000000000 00001095 [29] .debug_info PROGBITS 0000000000000000 000010f5 [30] .debug_abbrev PROGBITS 0000000000000000 00001669 [31] .debug_line PROGBITS 0000000000000000 00001860 [32] .debug_str PROGBITS 0000000000000000 000019b4gdb携带调试信息的exe2.安装gdbsudo yum install -y gdb3.快速认识gdb1 #include stdio.h 2 3 int Sum(int s, int e) 4 { 5 int result 0; 6 for(int i s; i e; i) 7 { 8 result i; 9 } 10 return result; 11 } 12 int main() 13 { 14 int start 1; 15 int end 100; 16 printf(I will begin\n); 17 int n Sum(start, end); 18 printf(running done, result is: [%d-%d]%d\n, start, end, n); 19 return 0; 20 }[user1iZ5waahoxw3q2bZ 26-4-16]$ gcc mycode.c -o mycode mycode.c: In function ‘Sum’: mycode.c:6:5: error: ‘for’ loop initial declarations are only allowed in C99 mode for(int i s; i e; i) ^ mycode.c:6:5: note: use option -stdc99 or -stdgnu99 to compile your code [user1iZ5waahoxw3q2bZ 26-4-16]$ gcc mycode.c -o mycode -stdc99 [user1iZ5waahoxw3q2bZ 26-4-16]$ ./mycode I will begin running done, result is: [1-100]5050[user1iZ5waahoxw3q2bZ 26-4-16]$ ./mycode No symbol table is loaded. Use the file command.需要加-g进入debug模式[user1iZ5waahoxw3q2bZ 26-4-16]$ gcc mycode.c -o mycode -stdc99 -g重新gdb mycode输入quit可以退出[user1iZ5waahoxw3q2bZ 26-4-16]$ gdb mycode GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7 Copyright (C) 2013 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-redhat-linux-gnu. For bug reporting instructions, please see: http://www.gnu.org/software/gdb/bugs/... Reading symbols from /home/user1/linux-learning/linux/26-4-16/mycode...done. (gdb) quit查看代码listb打 断点(gdb) b 19 Breakpoint 1 at 0x4005d9: file mycode.c, line 19.r运行(gdb) r Starting program: /home/user1/linux-learning/linux/26-4-16/mycode I will begin running done, result is: [1-100]5050 Breakpoint 1, main () at mycode.c:19 19 int n Sum(start, end); Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.3.x86_64c运行结束(gdb) c Continuing. [Inferior 1 (process 9036) exited normally]4.解决一些gdb难用的问题解决gdb难用的问题---cgdb推荐安装cgdb:• Ubuntu: sudo apt-get install -y cgdb• Centos: sudo yum install -y cgdb5.gdb/cgdb命令常见使用开始 gdb binFile退出 ctrl d 或 quit 调试命令命令 作用 样例 list/l 显示源代码从上次位置开始每次列出10行 list/l 10 list/l 函数名 列出指定函数的源代码 list/l main list/l 文件名:行号 列出指定文件的源代码 list/l mycmd.c:1 r/run 从程序开始连续执行 run n/next 单步执行,不进入函数内部,逐过程 F10 next s/step 单步执行进入函数内部, 逐语句 F11 stepbreak/b [文件名:]行号 在指定行号设置断点 break 10 break test.c:10 break/b 函数名 在函数开头设置断点 break main info break/b 查看当前所有断点的信息 info break finish 执行到当前函数返回然后停止 finish print/p 表达式 打印表达式的值 print startend p 变量 打印指定变量的值 p xset var 变量值 修改变量的值 set var i10 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 breakpointsdisplay 变量名 跟踪显示指定变量的值每次停止时 display x undisplay 编号 取消对指定编号的变量的跟踪显示 undisplay 1 until X行号 执行到指定行号 until 20 backtrace/bt 查看当前执行栈的各级函数调用及参数 backtrace info/i locals 查看当前栈帧的局部变量值 info locals quit 退出GDB调试器 quit开始[user1iZ5waahoxw3q2bZ 26-4-16]$ cgdb mycode除了之前那些命令1.b 打断点(gdb) b mycode.c:20 Breakpoint 1 at 0x4005de: file mycode.c, line 20. (gdb) b mycode.c:main Breakpoint 2 at 0x400595: file mycode.c, line 14. (gdb) b 17 Breakpoint 3 at 0x4005ad: file mycode.c, line 17.b 文件:行号b 文件:函数名也可以直接打断点b 行号info b查看断点(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005de in main at mycode.c:20 2 breakpoint keep y 0x0000000000400595 in main at mycode.c:14 3 breakpoint keep y 0x00000000004005ad in main at mycode.c:17Num断点编号d 断点编号 删除断点不能d行号(gdb) d 17 No breakpoint number 17.只能根据断点编号删(gdb) d 2 (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005de in main at mycode.c:20 3 breakpoint keep y 0x00000000004005ad in main at mycode.c:17 (gdb) d 1 (gdb) d 3 (gdb) info b No breakpoints or watchpoints.r运行程序(gdb) run Starting program: /home/user1/linux-learning/linux/26-4-16/mycode I will begin running done, result is: [1-100]5050 [Inferior 1 (process 9066) exited normally] Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.3.x86_64gdb不退出断点变化依次递增(gdb) b 19 Breakpoint 4 at 0x4005d9: file mycode.c, line 19. (gdb) info b Num Type Disp Enb Address What 4 breakpoint keep y 0x00000000004005d9 in main at mycode.c:19vs2022中f10逐 过程 f11逐语句n和snext/n逐过程step/s逐语句gdb会自动记录最新的一条输入指令bt查看当前函数栈帧(gdb) bt #0 Sum (s1, e100) at mycode.c:6 #1 0x00000000004005bc in main () at mycode.c:20finish执行到当前函数返回(gdb) finish Run till exit from #0 Sum (s1, e100) at mycode.c:6 0x00000000004005bc in main () at mycode.c:20 Value returned is $1 5050值会存到寄存器然后返回p变量打印指定变量的值int n Sum(start, end);执行两个动作一个call一个mov是将返回值从寄存器存储到变量n中断点可以被使能被启用和禁用Enb使能disableNum禁用断点enableNum启用断点调试的本质是什么1.找到问题---找到问题的命令 断点的本质是把代码进行块级别划分以块为单位进行快速定位区域2.查看代码上下文 finish-确认问题是否在函数内until-局部区域快速执行自己解决问题c从当前位置开始连续执行程序finish执行到当前函数返回然后停止until行号跳转到指定行display变量名跟踪显示指定变量的值每次停止时undisplay编号取消对指定编号的变量的追踪显示info locals查看当前栈帧的局部变量值6.三个debug技巧三个小技巧1.watch执行时监视⼀个表达式如变量的值。如果监视的表达式在程序运行期间的值发生变化GDB会暂停程序的执行并通知使用者• 如果你有⼀些变量不应该修改但是你怀疑它修改导致了问题你可以watch它如果变化了就会通知你.• 监视变量的变化2.set var确定问题原因更改⼀下标志位假设我们想得到-result(gdb) set var flag1 #更改flag的值确认是否是它的原因3.条件断点• 条件断点添加常见两种方式1.新增2.给已有断点追加• 注意两者的语法有区别不要写错了。• 新增b行号/文件名:行号/函数名 if i 30 (条件)• 给已有断点追加condition 2 i30 其中2是已有断点编号没有if• Cgbd分屏操作 ESC 进入代码屏i回到gdb 屏