欢迎来到博主的专栏:从0开始linux
博主ID:代码小豪
gdb是linux下的一个调试工具,与vs之类的IDEA的图形化界面的调试方法不同,gdb的调试方式是通过输入命令完成的。因此,想要使用好gdb这个工具,对gdb的命令的学习是必不可少的。
debug与release
我们代码生成的可执行程序分为两种,即debug版本和release版本,debug版本称为调试版本,通常对程序的试运行,调试操作都是在debug下完成的,release版本的可执行程序会对代码进行优化,且大小会比debug版本小很多(相同的代码下),但是release版本由于没有调试信息,因此无法对release版本进行调试。
优点 | 缺点 | |
---|---|---|
release | 运行快,存储小 | 不可调试 |
debug | 可调式 | 运行慢,存储大 |
通常来说,一个程序的release版本都是面向客户的发布版本。
在vs环境下,一个代码默认生成的可执行程序是debug版本的,而gcc默认生成的代码则是release版本的,因此,在使用gdb之前,来看看gcc生成debug版本的命令。
gcc [file] -g
如果你的linux系统没有安装gdb软件,可以输入下面的代码进行下载
sudo yum -y install gdb
如果当前账号没有sudo权限,请使用root账号,或者联系root账号拥有者进行下载。
gdb的常用命令
在开始使用gdb之前,我们先尝试如何生成一个debug版本的可执行程序。我们先写如下的一个code.c文件
1 #include<stdio.h>
2
3 int sum(int begin,int end)
4 {
5 int ret=0;
6 for(int i=begin;i<=end;i++)
7 {
8 ret+=i;
9 }
10 return ret;
11 }
12
13 int main()
14 {
15 int begin=1;
16 int end=100;
17 printf("%d\n",sum(begin,end));
18 return 0;
19 }
输入命令
gcc code.c -o code_debug -g -std=c11
此时,code_debug是一个debug版本可执行程序,我们就可以使用gdb对code_debug进行调试了。bgd打开文件的指令为:gbd [filename]
gbd code_debug
当我们的左侧命令栏显示(gbd):
就说明成功打开了文件。
gdb的指令
- list(可缩写成:l) 行号:显示源代码,比如我们输入命令:
l 10
如果想看接下来的源代码,按下enter键即可。
- l 函数名:显示对应函数的源代码
l sum
- run(缩写r):尝试运行代码,类似于vs中的f5。
- next(缩写n):逐过程,类似于vs中的f10
- step(缩写s):逐语句,类似于vs中的f11
cgdb
我们简单看一下gdb的使用过程,其实使用体验还是蛮糟糕的
最主要的原因在于调试的过程中并不能看到全面的源代码,而且整体的观感并不好,因此博主推荐大家使用cgbd这个软件进行调试。
cgdb是基于gdb的前端软件,在cgdb中使用的命令与gdb相同,但是cgdb提供了一个界面,我们可以通过这个界面来看源代码的执行情况。下载方式为
sudo yum -y install cgdb
绿色箭头表示当前调试进行的语句。在下面的命令行输入gbd指令可以进行调试。前面所讲解的gdb指令在cgdb中也是可以使用的。下面我们接着看看gdb还有什么指令。通过cgdb的界面可以更直观的看到。
断点
在vs中,f9可以对对应的语句打上一个断点,当调试过程中运行到了断点处就会停止。而gdb的断点也是同理,我们先来看看断点的指令有哪些。
- break(缩写b) 行号:在某一行设置断点
- break(b) 函数名:在该函数开头设置断点
比如我们想要在第16行设置断点,在sum函数开头设置断点,则输入
b 16
b sum
如果断点设置成功,则命令行会显示:
Breakpoint 1 at 0x400565: file code.c, line 16
而页面中的对应语句则会变红。
由于我们在第16行以及sum函数的开头设置了断点,可以发现对应语句的行号会显示成红色,说明这些语句被打上了断点。
我们尝试运行®,可以发现当调试进行到断点处则会停止,除非再次运行或者输入n,s进行逐语句,逐过程的调试。
比如:我们输入r开始运行。由于16行被打上了断点,因此调试会在运行到16行时停止,等待我们的后续指令
- continue(缩写c):继续运行,直到遇到下一个断点,或者直到程序结束。
如下,我们输入c,调试会来到下一个断点处,再次输入c则会完成调试。但是我们暂时先不这样做。
- finish:完成当前函数,当我们处在一个函数中时,输入finish可以退出当前函数,并且还能在命令行中看到函数返回值。
- info break(info b):查看断点信息
gdb中每个设置的断点都是有序号的,很多关于断点的指令都需要序号的配合。因此,info b这个命令还是很重要的。
- delete n:删除序号为n的断点
- disable n:禁用序号为n的断点
- enable n:启用序号为n的断点
比如,我们向暂时停用行号5的断点(通过info b知道,该断点的序号为2)。因此输入
disable 2
被禁用的断点会显示为黄色,此时运行调试,调试不会在经过黄色断点(未启用的断点)时,停止调试。
如果想要重新启用被禁用的断点,则使用enable指令
enable 2
重新启用的断点会变回红色,此处不展示。
如果要想删除某个断点,则使用delete指令
delete 2
监视
在调试的过程中,有时候会需要对一些值进行监视。接下来我们来介绍一下常用的gdb的监视指令
- p [表达式]:打印表达式的值,包括函数计算的返回值。
p sum(1,99)
- p [变量]:打印变量的值,要注意变量在当前位置的生命周期要存在。
由于i的生命周期在sum函数当中,因此在main函数当中无法打印i的值。
- display 变量名:跟踪查看一个变量,每次停下来都显示它的值
- undisplay n:取消对序号n的变量设置的跟踪
其实display的功能比较像vs当中的监视窗口,比如我们尝试在sum函数当中对i和ret进行监视。
可以发现,每当调试停下来时,就会输出当前的监视的值。
- info display:获得当前监视的变量的信息。最主要的是获得它们的序号。
- watch [变量名]:和display都是监视变量的值,但是不同的点在于,watch只有在变量的值发生改变时才会显示
当ret改变时,新旧的值都会被显示。
如果不想要监视点,使用delete 序号
指令即可。info b
不仅能查看断点序号,也能查看监视点序号。
条件断点
所谓的条件断点,就是当程序执行到断点处时,如果条件为true时,在该断点处停止。
b [line] if [boolexp]
比如我们在第8行加上一个条件断点,该条件为i==10.则输入
b 8 if i==10
此时运行程序,当i==10为true时,在该断点处停止。
如果想要将断点加上或修改条件,则输入condition [断点序号] [boolexp]
比如将上面的断点的条件修改为i==20.我们先输入info b
查看该断点的序号
得知该断点的序号为1,接着输入
condition 1 i==20
此时该断点的条件修改为i==20.