目录
第一条指令是list/l 可以缩写成l,l+数字,就是显示行号信息,默认从上次位置开始显示10行。
接着由于我们用过Vistdio,调试时则使用F5来编译通过打断点来直接按顺序执行,F10来逐过程,F11来逐语句,F9来设置断点以及手动禁用断点(不删除只不过是根据需求暂时禁用)。
添加删除结束后,还有使能(enable)断点,也就是vs下的禁用和启用断点
断点的设置说完后则是调试,也就是vs下的f10逐过程、f11逐语句
其次再学习一个命令c/continue 继续的意思,意义在于断点与断点的跳跃。
或者使用until+行号,这也是一个命令,直接跳到指定行号。
当然看到这里肯定也收获不少,但是gdb很乱不方便我们使用,还不如图形化界面,此时我们就需要下载一个新的东西叫cgdb。
其他的还有finish命令来直接执行一整个函数,方便排查、搜寻错误。
接下来再学习一个watch,通过watch也相当于打个断点,watch所打断点的变量变了,就会显示出来
前情提要
在vs下程序有debug版本和release版本,debug版本方便程序员调试,release版本也就是发布版本,是供用户调试使用的。
gcc/g++的可执行程序默认是release版本。
上图代码是个简单的小程序,通过这个代码我们来测试一下gcc下编译后的可执行程序是否是release版本。
通过使用makefile来进行编译
debug版本则需要加“-g”也就是debug的最后一个字母。
gcc -o myexe-debug test.c -g
myexe的文件大小明显比myexe-debug文件大小要小
readelf,elf大致意思是查看文件的格式.
自上往下看两者图其实是紧挨着的代码和显示结果。
只有后缀为debug的文件显示了有结果。
注意学习gdb调试工具,必然是要以debug版本的可执行程序为基准。
再一个通过file指令也可以对比出结果。
如何下载gdb呢?
本人用的是Ubuntu操作系统,yum是在centos上用,出现了一个问题,就是yum下载不了,当查阅了相关资料可以看一位网友的博客分享
使用指令“gdb”可以查看是否下载了gdb
如果没下载就需要指令:“sudo apt-get install gdb”
下载完后使用指令:“gdb --version”来查看下载gdb后的版本信息
下面就是如何使用gdb来进行调试了。
在命令行输入gdb就能够进入gdb界面
输入quit来退出gdb
通过输入gdb myexe-debug来进入调试模式
此时就要学习一些gdb里面的指令了
第一条指令是list/l 可以缩写成l,l+数字,就是显示行号信息,默认从上次位置开始显示10行。
如上图,第二次命令行什么也没输入,是因为gdb会记录最新的一条命令,直接回车就是默认执行该指令。
上图为l+函数名 表示列出指定函数的源代码
上图为l+文件名:行号 表示显示指定文件第n行的代码
接着由于我们用过Vistdio,调试时则使用F5来编译通过打断点来直接按顺序执行,F10来逐过程,F11来逐语句,F9来设置断点以及手动禁用断点(不删除只不过是根据需求暂时禁用)。
linux操作系统下也有对应的指令。
比如打断点:break/b+行号
行号打断点后也有删除断点,当然如图还有info b的意思是查看断点信息
删除指定断点:delete+断点编号
删除所有断点:delete+breakpoints
添加删除结束后,还有使能(enable)断点,也就是vs下的禁用和启用断点
disable+breakpoints:禁用所有断点
enable+breakpoints:启用所有断点
使用quit先退出当前调试,从新做示范,差别我用红色方框标注出来了。
断点的设置说完后则是调试,也就是vs下的f10逐过程、f11逐语句
在linux下如何呢?
r/run ,F5
n/next表示单步执行,不进入函数内部,也就是f10;
s/step表示单步执行,进入函数内部,f11
接下来是类似VS下的监视窗口
以上是:display+变量名 跟踪显示指定变量的值
以上是:undisplay+编号 取消对制定编号的变量的跟踪显示
上图明显undisplay跟dispaly不一样,两者的差别跟b打断点相似,都是有编号的,并且编号是递增的。
接下来是p(print打印)的使用
如图是循环体的两次循环,以及i的两次++,p打印两次i的结果不同。
这里的i是100,那如果是1000、10000呢?那调试就会很鸡肋了。
如何直接跳过并且执行整个循环呢?
首先在Sum函数里打一个断点到return返回值的位置。
其次再学习一个命令c/continue 继续的意思,意义在于断点与断点的跳跃。
或者使用until+行号,这也是一个命令,直接跳到指定行号。
当然看到这里肯定也收获不少,但是gdb很乱不方便我们使用,还不如图形化界面,此时我们就需要下载一个新的东西叫cgdb。
CentOS:sudo yum install -y cgdb
Ubuntu: sudo apt-get install -y cgdb
通过cgdb --version来查看安装结果和版本。
其他的还有finish命令来直接执行一整个函数,方便排查、搜寻错误。
如图finish直接结束整个Sum函数,并且返回结果。
接下来看一下cgdb的界面
这里有两个窗口通过ESC键来进入上面的页面,通过i来进入下面的页面。
很显然打过断点的行有红色行号标记,cgdb更方便使用。
接下来再学习一个指令叫:bt 来查看堆栈情况
以及info local 来查看当前栈帧局部变量的值
相当于VS下的自动窗口
问:调试的本质是什么?
answer:找到问题!而解决bug是目标,因为解决bug是人来操作的。
通过断点+finish+until+c:对大的代码块进行区间debug---》快速定位问题的位置
接下来再学习一个watch,通过watch也相当于打个断点,watch所打断点的变量变了,就会显示出来
这个watch可以用于const常量的watch打断点,因为如果出现没写const,而这个值变了,就会显示出来变化的情况。
再学习一个set var来修改变量的值
比如修改一下代码,增加一个flag,看结果。
接下来makefile用myexe来演示,不用myexe-debug(就改个名字而已)。
如上代码,通过display表达式的值,until到11后发现表达式为0,但是p sum后值是正确的,那么就可以锁定错误的值为flag,但是还要quit出去vim去修改flag的值,但是我现在立刻需要个结果怎么办?
这时就需要set var 变量=变量值
那么如何像vs那样设置条件断点呢?
有两种情况一种是1.新增,另一种是2.给已有断点追加
如上代码:b+行号+if+判断条件就可以设置条件判断,即使用finish结束函数,也只会在此断点打断。
注意:打断点的行号要写循环体内,而不是7,eg:b 8 if i==10,在此之前可以使用display来观察i的值的情况。
上图是两次finish才结束函数体。
接下来是已经存在的断点进行条件判断添加:
通过condition+断点编号+新增条件来给已有的断点设置条件判断
注意与直接设置条件判断断点的区别在于没有if,并且用了condition+断点编号+新增条件的方式来使用。
习题
若基于Linux操作系统所开发的源文件名为test.c,生成该程序代码的调试信息,编译时使用的GCC命令正确的是?
A.gcc -c -o test.o test.c
B.gcc -S -o test.o test.c
C.gcc -o test test.c
D.gcc -g -o test test.c
答案解析
gcc常见选项:
-c 汇编完成后停止,不进行链接
-E 预处理完成后停止,不进行编译
-S 编译完成后停止,不进行汇编
-o 用于指定目标文件名称
-g 生成debug程序。向程序中添加调试符号信息
根据各个选项作用分析,得到正确答案为D,使用-g选项生成包含有调试信息的可执行程序