Linux--gdb的使用

1. 部分指令

执行代码统称为翻译过程,程序翻译过程的基础知识如下:

  1. 预处理(进行宏替换、去注释、头文件展开等)
  2. 编译(生成汇编)
  3. 汇编(生成机器可识别代码)
  4. 链接(生成可执行文件或库文件)
  • 预处理

创建test.c,对应指令解析为:

gcc -E test.c//test.i

-E表示开始翻译程序,完成预处理之后停下来,此时产生的文件为test.i。

这条指令不好用,因为打印的是所有输出结果,不便于观察,所以经常这样写:

gcc -E test.c -o test.i

-o代表指定生成某种文件,同样的,现在需要完成预处理之后停下,那么对应生成的应该是test.i文件。

  • 编译
gcc -S test.i -o test.s//前提是要产生了.i文件

-S表示开始翻译程序,完成编译之后停下来,此时产生的文件为test.s,里面包含程序对应的汇编语言。

  • 汇编

为什么需要这一步?因为计算机不可以直接执行汇编语言,需要将汇编语言转化为二进制。

gcc -c test.s -o test.o//前提是要产生了.s文件

此时产生文件为test.o。

和前面同理,不过这里的-c是小写,代表执行完汇编过程就停下,也就是生成机器可识别的代码,其实就是二进制程序,但是此时还是不能被直接执行;

  • 链接

将生成的所有.o文件以及对应的头文件打包起来,就成为了一个库;为什么需要头文件?因为需要提供接口。

gcc test.o

这种方式默认形成的是a.out,也可以通过下列这样形成指定名称的可执行文件

//两种方式一样
gcc test.c -o test
gcc -o test test.c

2. 调试

2.1 产生调试信息

Linux下生成的可执行程序默认是realase版本的,需要转换成debug版本

执行下列指令

gcc -o test.c test -g

-g的意思是添加调试信息,也就是debug版本。

2.1 命令行调试

进到(gdb)命令行,先让程序跑起来:

(gdb)run;//(gdb)r
2.1.1 查看行号

不断执行list或 l 可以查看到行号,也就可以明确在哪个地方打断点:

(gdb)list//(gdb)l
(gdb)l 1//l n代表从n行开始

还可以通过函数名查看:

(gdb)l main;//查看main函数主体

但是这种方式会带有上部分代码的几行代码,是为了和上部分代码形成关联性。

2.1.2 断点
  • 打断点

断点全称breakpoint,简写为b,指定第n行打断点:b n

(gdb)b 5;//第5行打断点
  • 查看断点信息
(gdb)info b;//查看断点信息

断点信息里面包括了行号、地址等,还有该断点是否启用。

  • 运行断点

打完断点以后,再次执行run,可以看到程序跳转至对应断点处。

运行分为逐过程next(简写为n,不进入函数)和逐语句step(简称s,需要进入函数)。

(gdb)next;//(gdb)n
(gdb)step;//(gdb)s
  • 监视

gdb中的监视是display,显示某个值的信息,包括所在行、值、地址等,该指令不能简写。

(gdb)display n;//显示n的数值信息
(gdb)display &n;//显示n的地址信息

每次执行该指令后,再多次执行n或者s指令,可以直接常显示对应值的变化情况,就不用一直调用display了,这个设定也包括了你接下来监视的变量,和vs2019中类似。

若此时想删除变量,可以执行undisplay,但是后面跟的不是某个变量,而是该变量开头对应的代号:

(gdb)undisplay 1;//删掉监视窗口中代号为1的变量
(gdb)undisplay 1 2;//删掉监视窗口中代号为1和2的变量

若只想查看一次:

(gdb)p n;//只查看一次
  • 退出断点

finish表示直接结束当前函数

(gdb)finish;//直接得到函数返回值

另一种方式叫做continue,表示跳到下一断点:

(gdb)continue;//直接跳到下一断点

还有一种方式until,表示直接运行到某一行:

(gdb)until n;//直接跳到第n行
  • 删除断点和禁用/启用断点

删除断点delete,也是要按照对应的编号,而不是指定哪个行的断点:

(gdb)d 2//删掉2号断点

禁用断点undisable:禁用后断点状态由y->n

(gdb)disable 2//禁用2号断点
(gdb)enable 2//启用2号断点

3. 程序崩溃时如何找到行号

有时候程序崩溃比较难精确找到行号,有一种方式是利用core dump标志位。

这个标志位的作用就是:如果程序异常退出,它会被置1,并且生成core文件。

但是这有前提:

首先在云服务器上,Linux中的这个标志位的功能是被关闭的。所以想要打开这个功能,要先向core file size中写入大小,表示打开这个功能,然后core dump标志位才会有上述功能。

打开这个功能:

执行ulimit -a查看系统资源,第一行的core file size是0,说明默认关闭:

在这里插入图片描述

我们可以先设置它为任意大小:

ulimit -c 10240

在这里插入图片描述

这表示系统允许你使用core dump位,此时我们故意写出一个浮点数错误的程序:

int main()
{
    int a = 0;
    a /= 0;
    return 0;
}

运行结果可以看出直接打印了浮点数错误,并且还增加了一个core.1678文件:

在这里插入图片描述

每次产生的core文件会不一样,也就是每次执行可执行文件,OS给你的调试的信息不一样,然后就可以进行gdb调试:

在这里插入图片描述

可以清楚地看见,由于出错收到的信号、出错的行号、出错的代码都已经被找出来并打印到了屏幕,这种方式叫做事后调试。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

久菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值