文章目录
1. 前言
软件发布的模式有两种,一种是debug
模式,另一种是release
模式,一般程序员写软件都是在debug
模式下的,如果软件写好,并且自测也通过的话发布软件是在release
模式下发布的。比如我们手机应用,电脑应用的发布模式都是release
模式。程序员写完一个软件的代码,交给测试员测试都是把release
版本交给测试的,测试通过就会发布给用户去使用。但Liunx下编写好的代码无法直接测试,因为gcc/g++
默认的模式是release
模式。
- 我们要想我们的程序在
debug
模式下运行的话,我们就需要在翻译的时候加上-g
选项
- 保存退出后我们再次make一下重新形成了可执行程序
上面是没有加-g
选项的,下面是加了的,我们会发现下面的可执行程序的体积大于上面的,下面的就是debug
版本
所以-g
选项,让最后形成的可执行程序添加调试信息—debug
模式!程序要调试,必须是debug
模式!
2.关于gdb
2.1 快速认识gdb
- 我们首先生成一个
mycode
可执行程序,然后进行gdb mycode
就进入到gdb
里面了
quit+回车
就退出来了
2.2 安装cgdb
cgdb
和gdb
本质上是一摸一样的,只不过cgdb
能够把我们的代码动态呈现出来
• Ubuntu:sudo apt-get install -y cgdb
• Centos:sudo yum install -y cgdb
cgdb
的上面是我们的代码,下面是我们的调试信息📌:cgdb
分屏操作Esc
进入代码屏,i
回到gdb
屏
l mycode.c:1
:从第一行开始显示
2.3 gdb命令
list
:查看源代码b+行号
/b+文件名:+行号
/b+ 文件名:函数名
:直接在第几行打断点或哪出位置打断点info b
:查看断点d+断点编号
:删除断点 注意:不能使用d+行号
删除断点r/run
:让程序运行起来c
:让程序直接跑完quit
:退出next/n
:逐过程,相当于vs中的F10
step/s
:逐语句,相当于vs中的F11
,gdb会记录最新的一条指令,如果想一次性重复多次s
,只需在一个s
后回车即可
属性:gdb不退出,断点变化一次递增。断点可以被使能
以上是一些常用命令,我将gdb
的命令整理成表格,如下所示:
命令/缩写 | 作用 | 样例 |
---|---|---|
list /l |
显示源代码,从上次位置开始,每次列出10行 | 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 |
2.4 调试 & 断点
调试的本质是什么?
- 找到问题
- 查看代码上下文
- 解决问题
断点的本质:把代码进行块级别划分,以块为单位,快速定位出现问题的区域
3.常见技巧
3.1 watch
如果我们想要监视某个变量,并且我们十分关心这个变量的变化,我们就可以用watch
,它可以新老对比,我们就直接可以看到它的变化了。
- 比如我们想查看
result
info b
的时候我们会发现多了一个watchpoint
- 我们继续正常调试,就会发现多了新老对比
- 不用了的话我们可以直接
d+断点序号
进行删除
📌注意:
- 果你有一些变量不应该修改,但是你怀疑它修改导致了问题,你可以
watch
它,如果变化了,就会通知你.
3.2 set var确定问题原因
set var
也是我们比较常用的调试技巧,它可以确定并直接更改我们代码中的错误,而不需要去源代码中去改,。
- 例如在这段代码中错误是
flag=0
导致的,修正方案是将flag
改为1
3.3 条件断点
- 如果我们既不想一个断点被删掉又不想一个断点被使能掉,让它在某种条件下触发。比如我们想让
i=10
时触发断点。b + 行号+条件
- 如果不需要了也可以直接
d+断点序号
- 如果我们想要已经存在的断点加上触发条件,我们可以
condition+断点序号+条件
给已经存在的3号断点加上触发条件
👍 如果对你有帮助,欢迎:
- 点赞 ⭐️
- 收藏 📌
- 关注 🔔