【Linux 学习计划】-- Linux调试工具 - gdb cgdb
目录
先导概念 debug && release && -g 选项
gdb 的操作指令
cgdb
debug 的相关建议
结语
先导概念 debug && release && -g 选项
首先我们需要知道的是,软件开发中有两种模式,一种是debug,一种是release
这两种的区别在于,release会优化,并且不能调试,且这是给用户用的模式,所以我们测试也是用的这个模式
而debug模式则是用来检查代码逻辑,检查代码错误的,这其实是给程序员用的
而我们的debug为什么可以调试而release不能呢?本质上是因为,debug版本的可执行文件会加上对应的调试信息(而release没有调试信息,所以就不能调试)
同时,我们的release也是不需要这些调试信息的,试想一下,将调试信息给用户,是让用户自己调吗?浪费带宽等资源传一些没用的数据?这不现实
而我们在Linux中,当我们使用了gcc或者g++时(下文统一用gcc的代码做演示,因为两者都差不多),默认用的就是release,而如果要转换成debug模式的话,我们只需要在gcc后面加上-g选项即可
如下图:
(这是默认也就是release的makefile)
(这是debug的makefile):
下图,我们可以明显看到大小是不一样的,上文说了,这是由于有调试信息的存在
我们通过readelf -S 去查,筛选出debug信息时也能发现,确实只有debug的版本有对应的调试信息,而release版本查出来是空的
gdb 的操作指令
首先,我们gdb的操作是针对可执行程序的,如下图,针对的就是可执行程序:
另外,gdb是系统默认自带的,所以不需要下载安装,直接用即可
接下来就是操作指令
line 显示 也可以简写成 l,用法为 l 0 、 l 文件名:行数 、 l 文件名:函数名
run,也可以简写成r,直接用,表示将程序跑起来的意思
但是如果没有打断点的话,会直接把整个程序跑完
有断点则会停在断点处
这里的b 17表示在第17行打一个断点,所以 r 了之后就会停在断点处
breakpoint,打断点,也可以简写为 b,三种用法和最上面的 line / l 是一样的,这里不做解释
另外,我们的断点是有断点编号的,当我们使用info b的时候,就能看到最左边有一排数字,我们后续在disable、enable中都要使用这些编号
图例如下:
info,这个可以简写为 i,可以联合 b,表示查看断点,图例就是上面那张图的最后一个操作
info(i)还有一种用法,就是info locals,这个用法的作用的查看当前栈里的所有变量
比如我写了一段程序,里面的变量有i,a,b,count,那么info locals就会直接将所有变量的信息显示出来:
disable、enable
这两个,一个是禁用断点,一个是解除禁用
比如我有一个断点我待会儿可能还要用,但是我在这一次测试里面不会用到他,但我又不想把他删掉,所以我可以先disable + 断点编号把他禁用,下次要用我再enable + 断点编号解除禁用即可
n / next、s / step
这两个,一个是逐过程,一个是逐语句
逐过程就是,我们遇到的函数不会具体进入函数内部,会直接将该函数执行完
而逐语句就是会进入函数内部
比如我们现在运行到第20行,如果我们是n,那就会走到第21行,如果是s,那就会进入函数内部:
p / print:查看变量内容或者查看变量地址
就好像调试窗口,只不过只能敲一次指令显示一次:
但是按照 p 的做法,我们每一次想看都要敲一次指令,有点挫了,所以我们就有了下一个指令
display && undisplay
这个就相当于真正的窗口了,只不过我们display的时候,和p的用法是一样的,但是undisplay的时候,由于display会有和断点一样的编号,所以我们undisplay需要输入这样的编号:
我们还有一个需求就是,为了快速锁定项目中的问题出在哪里,所以我们需要逐断点查询
c / continue:逐断点
比如我们打了很多断点,如果说n和s都是执行一次就跳到下一条代码,那么 c 就是跳到下一个断点处
还有就是,当我们只想快速看看当前函数能否达到相应的效果,就是想快速看看时,我们就可以用下面这一条指令
finish,直接用,如下:
如果我们在一个函数中,进入了一个很大的循环,出不去了,或者说就是想单纯跳到第几行代码,中间的全部给我执行一遍,那么我们就可以用这条指令:
until,后面要加行号,表示你要跳到第几行
set var
比如我们在循环中,可以直接用 set var 将某一个变量设置为某一个值
或者是我们可能一个项目,就某一个值跑不了,我们就可以设置成这个值看看
但是我们需要知道的一点是,set var之后的值可能是错的,如上图,本来应该是sum == 5050,但是我们直接set var之后,sum的结果就不对了,需要注意
bt,这是个小命令,是用来查看堆栈的:
cgdb
先解释一下,cgdb相当于是gdb的加强版
但是默认不会自动安装,所以需要我们手动安装:
Ubuntu:sudo apt install cgdb
centos:sudo yum install -y cgdb
所有用法和gdb是一样的,照着用即可
debug 的相关建议
叠个甲,这只是我个人认为可以试一试的方法,如果大佬有更舒服的用法可以在下面评论区分享一下,主包也想进步啊
首先我们的gdb只是一个工具,是帮助我们找出问题所在的,但是真正解决问题的时候,还是要靠我们程序员自身
而当我们遇到问题的时候,可以先使用一眼盯帧法(我的眼睛就是尺),可能就是一些语法问题,肉眼就能看出来
接着如果看不出来,就可以用打印法,在相关地方printf或者cout一些内容,这样基本就能解决大部分问题了
最后实在不行了,再使用cgdb或者gdb,但是使用同样有技巧,就是,我们可以用断点+二分的方法快速判断出问题出在哪里(比如有1000行代码,我们先在500行打个断点,看看前500行能不能跑,没问题就是后500行的问题,就接着在750行打断点,以此类推,快速锁定)
最后到地方了,再用一眼盯帧法,打印法,或者干脆就是n,s,c,display一步步往下看
结语
这篇文章到这里就结束啦!!~( ̄▽ ̄)~*
如果觉得对你有帮助的,可以多多关注一下喔