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

这个有带-g所以这个具有编译功能

而且我们可以发现带了-g这个可执行程序的大小明显的发生了变化,大小变大了
二,调试器常见命令
| 命令 | 作用 |
|---|---|
| list/s | 显示源代码,从上次位置开始,每次列出10行 |
| list/函数名 | 列出指定函数的源代码 |
| list/l 文件名:行号 | 列出指定文件源代码 |
| r/run | 从程序开始连续执行 |
| n/next | 单步执行,不进⼊函数内部, 逐过程 F10 |
| s/step | 单步执行,进⼊函数内部, 逐语句 F11 |
| break/b [文件名:]行号 | 在指定行号设置断点 |
| break/b 函数名 | 在函数开头设置断点 |
| info break/b | 查看当前所有断点的信息 |
| finish | 执⾏到当前函数返回,然后停止 |
| print/p 表达式 | 打印表达式的值 |
| p 变量 | 打印指定变量的值 |
| set var 变量=值 | 修改变量的值 |
| continue/c | 从当前位置开始连续执行程序 |
| delete/dbreakpoints | 删除所有断点 |
| delete/dbreakpoints n | 删除序号为n的断点 |
| disable breakpoints | 禁用所有断点 |
| enable breakpoints | 启用所有断点 |
| info/i breakpoints | 查看当前设置的断点列表 |
| display 变量名 | 跟踪显示指定变量的值(每次停止时) |
| undisplay 编号 | 取消对指定编号的变量的跟踪显示 |
| until X行号 | 查看当前执行栈的各级函数调用及参数 |
| info/i locals | 查看当前栈帧的局部变量值 |
| quit | 退出GDB调试器 |
三,调试器命令的使用

当生成一个带 -g 的可执行程序,成功的生成之后使用 “gdb+生成的可执行程序” 将会让这个程序进入调试阶段

执行成功之后将会来到这个界面,这个时候我们就可以使用调试的命令了

1,list/l
如图l为查看代码,但是一次性只能查看10行,如果要接着查看代码就要接着使用l命令,
但是gdb回自动记录最新的一次输入指令所以我们在输入命令行中什么都不写直接按回车就可以直接执行上一次使用的指令,也就是l,所以我们现在想看后面的代码就直接按回车就行了

如图我们直接按回车,程序会自动执行l查看后面的代码,到了最后一行,程序会直接告诉你现在已经是最后一行了,如果你又想从头开始查看代码就直接输入 l 1也就是会到第一行重新查看代码

如图
2,break/b+代码行号/代码里面的函数名
如果想要给其中都某一行代码添加断点,就是使用break/b+代码行号,就是表示你要在代码的那一行加短点

如图,我们直接break/b+加代码行号,就成功的在代码的第6,7,17这三行代码设置了断点,在这个程序运行到其中的断点行,这个程序就会停下来,如果我们需要查看我们自己设置的断点行的话,我们直接使用info+break/b就可以查看自己设置的所有代码的断点了

3,info+/break/b
如图直接使用info+break/b就可以查看自己设置的所有断点
Num:表示你给某一行代码设置了断点,系统给这个断点代码设置的代码编号,以后使用删除断点指令就要使用这个系统给的代码编号进行删除,一般第一个设置的断点代码编号就是1,然后依次类推
Type: 表示类型,breakpoint就是表示这个类型是一个断点
Disp:表示这个断点是临时的还是保持的,临时断点就是这个断点只会触发一次,触发一次之后这个断点就自己删除,保持断点就是这个断点会一直都在,不管这个断点执行多少次,只要你不对这个断点做任何的修改或者删除
End: 表示这个断点是否开启,y表示yes就是开启的意思,n就是表示no就是关闭的意思
Address: 顾名思义地址的意思
what: 前面的in…就是表示它存在这个程序的哪个函数块里面,at…就是表示它属于哪个文件的第几行代码
4,delete/d+系统给的代码编号/breakpoint
如果需要删除单个断点就使用delete/d+系统给的代码编号

可以发现我们一个一个成功的删掉了我们需要删除的断点,如果我们需要一次性删掉我们设置的所有的断点就是使用d/delete+breakpoint

如图我们先查看了自己设置的断点,然后成功的通过了d/delete+breakpoint一次性删除了所有的断点
5,disable+系统给的代码编号/breakpoint
如果在我们日常调试代码中,其中一个断点不想使用又不想删除我们就需要使用disable+系统给的代码编号表示禁用断点

如图我们就成功的禁用了编号为1的断点,通过查看可以发现编号为1的断点并没有被删除,这个断点还存在只是表示断点开关的End那一列的编号为1的断点变成了n,就是表示这个断点被关闭了,如果我们一次性想禁用所有的断点就是使用disable+breakpoint

如图我们就能使用disable+breakpoint一次性禁用所有断点
6,enable+系统给的代码编号/breakpoint
可以禁用断点就肯定有开启断点,开启断点就是把被禁用的断点开启接着继续使用,命令为enable+系统给的代码编号

如图我们成功的开启了一个被禁用的断点,如果我们要一次性开启和使用被禁用的所有断点我们就要使用enable+breakpoint

四,认识cgdb调试器
cgdb和gdb一样都是Linux中的调试器,他们的命令一样,生成的可执行程序一样都是加上-g,只不过使用什么调试器就是使用cgdb/gdb+可执行文件,使用cgdb+可执行文件就是使用cgdb的调试器,使用gdb+可执行程序就是使用gdb调试器,但是现在基本上都是使用cgdb调试器因为更利于调试代码

我们使用cgdb调试代码可以很明确的发现这个调试界面分两部分,上半部分是代码区域,下面就是命令部分,在这个调试界面下我们就能更便捷能一边输入命令一边查看代码,就完全可以说不需要list/s命令了,而在gdb调试器下查看代码就只能使用list/s来查看代码
ESC:从命令模式切换为代码模式
i:从代码模式切回命令模式
在代码模式中有几个命令
| 命令 | 作用 |
|---|---|
| gg | 跳到文件开头 |
| G | 跳到文件末尾 |
| /关键字 | 搜索关键字 |
而且我们在cgdb调试器下打断点的话代码上我们还能直接看到哪一行是断点

如图我们可以明显的看到,有断点的代码他的代码行会变成红色,没有的就是白色
五,补充调试器其它命令
1,p+变量

如图我们在函数的入口出打了一个断点,然后我们开始运行这个程序,这程序会在当前变量处停下来,我们就可以使用p+变量来查看当前的变量值是否传参成功,然后我们可以明确的看到这个s等于1,p=100说明这个传参是成功的,我们也可以在日常中通过这个命令来进行查看值是否是正常的来判断bug存在的位置

p不仅可以加一个变量来查看当前变量的值,也可以通过p+一个表达式来判断是否正确来查看bug存在的位置,可以高效的提高我们的排查bug的速度
2,s/step(逐语句)

简单的说就是在程序运行中触碰到断点,程序停止了我们在命令行中按s,我们就能一步一步的运行代码,帮助我们排查bug
3,n/next(逐语句)

简单的来说就是我们在排查过程中来到了一个函数调用的地方,我们确保这个函数没有问题不想进入这个函数里面为了节省时间想直接获取相应的值,我们使用命令n/next就行了
4,display+变量
display+变量就是无时无刻都在告诉你这个变量当前值是多少也可以说就是监视一个对象,如图我监视了一个变量n,然后不管我以后在命令行中输入什么指令,然后都会在我输入命令之后告诉我你监视的变量n当前值是多少
5,undisplay+系统给的代码编号

undisplay+系统给的代码编号等于取消监视某个变量的值如图在我们运行过程中我们发现了系统监视了其中一个变量,但是我们现在不想监视这个变量了我吗就要使用undisplay+系统给的代码编号来取消监视这个变量,然而系统代码编号已经告诉你了就是这个变量左边 :前面的数字,我们直接使用undisplay+这个数字就行了
6,watch+变量
watch命令和display类似,但是大多数时候使用watch的较多,display是你监视的值不管有没有发生变化它都会告诉你当前你监视的变量是多少1,而watch是只有当变量发生了变化它就会告诉你变量的旧值还有现在的新值

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


如图,简单来说就是修改变量的值,然后修改的值还是全局有效
8,条件断点
简单的说就是根据自己的需要自己增加一个条件断点

如图就是自己设置的一个条件断点,也就是直有到达特定条件的时候,条件断点才会触发

然后条件断点的条件也是可以修改的如图,成功把i3才能触发的条件改成了16才会触发断点
注意:
条件断点添加常见两种方式:1. 新增 2. 给已有断点追加
注意两者的语法有区别,不要写错了。
新增: b 行号/⽂件名:行号/函数名 if i == 30 (条件)
给已有断点追加: condition 2 i==30 , 其中 2 是已有断点编号,没有if
9,quit/q
就是退出调试器,代码调试完成结束调试
更多推荐




所有评论(0)