【linux】gdb

鼠扑  金牌会员 | 2024-12-27 19:28:27 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 864|帖子 864|积分 2592

gdb

软件发布的模式有debug和release。

linux下我们编译好的代码,无法直接调试。
因为gcc/g++默认的工作模式是release模式。
我们在Makefile里翻译的时候加上-g选项:

这样我们也能生成一个可实行程序,且对比之前生成的release版本,可以看到体积变大了一些。


而如果是release版本:

可以看到不包含调试信息。
程序要调试,必须是debug模式。也就是说编译时要加-g选项
gdb未来调试程序必须调试携带调试信息的exe
gdb

gdb的学习分为三步走:快速认识gdb;gdb命令的学习;解决一下gdb难用的问题,三个debug技巧。
正文

那么我们如今在名为gdb的目录下创建一个mycode.c文件,写这样一段程序:

然后我们如果普通地去编译这段代码就是:
gcc mycode.c -o mycode,然后因为我们在for循环括号中举行了定义变量,无法编译乐成:

以是我们需要在编译时手动加上c99的尺度:
gcc mycode.c -o mycode -std=c99

这样就能编译乐成了,但是我们不想要release版本的可实行程序,而想要有调试信息的debug版本,以是我们还需要带上一个-g选项:

如今我们就能gdb mycode,进入gdb环境了:

怎么退出gdb环境呢?

quit
进入gdb后第一件事,我们要检察我们所有的源代码:

list/l/l 文件名/l 行号

通过list大概简写l,就可以检察当前所有的源代码;
我们也可以通过l背面带文件名来指定我们要看的文件;
我们还可以在l背面带上行号,来指定从某一行开始显示,比如带个1就可以从头开始显示,但它不会显示全,我们再按下回车后会接着显示:

b 行号——打断点

我们通过b背面跟行号,可以给这一行打上断点;

也可以b先跟文件名,再跟行号,这样打断点,b mycode.c:20;
还可以b先跟文件名,再跟函数名,这样打断点,b mycode.c:main
在VS中,我们是通过f9来打断点。
在我们打了断点的行上,还会发现字体直接变红了:


但是我们有直接检察断点的命令。
info b——检察断点


d 断点编号——删除断点

与打断点时的b跟着行号差别,我们不能d跟着行号来删除断点,而是要d跟着断点的编号来删除断点。
这个编号就是我们在info b命令之后看到的编号。

在删掉所有的断点,再次打断点并info我们会发现:

即使前3个断点我们都已经取消了,我们再重新打断点时仍然编号为4而不是从1重新开始,因为:
gdb不退出,断点编号依次递增。
退出重新gdb进来后打断点,就可以发现断点重新从1开始编号了。
r——让程序运行起来

全称是run,相当于f5,也就是调试并运行(我们一般会先打上断点)
(ctrl+f5在VS中是运行不调试)
我们可以看到程序运行起来之后自动在我们打了断点的这一行停下来了。

c——让程序不停下来直接跑完

cgdb可以动态出现我们的代码

这个需要我们先安装一下
(centos7):sudo yum install -y cgdb

可以看到,cgdb的效果是上面是代码,下面是gdb的调试。
逐过程(VS下的f10;把函数当整体直接跳过)



然后我们按下n(全称是next)

可以看到,就运行到第17行了,可以看出是逐过程。
然后我们再按一次r,会发现并没有直接跑完程序,而是停在return 0;之前,而且询问我们要不要重新调试:

按下y,发现又重新运行并再次停在了断点处:

逐语句(VS下的f11;进入函数详细调试)

s(全称是step)

可以发现,如今我们就进到Sum函数里了:

然后我们反复按s,就可以往下逐语句运行


其实我们不需要反复s也可以一条条往下实行,按回车就可以,这是因为gdb会记载最新的一条输入指令,按回车就是实行近来的那条指令。

小tips

注意gdb作为命令时背面跟的是可实行文件而不是源文件,否则我们没法乐成进入gdb环境:
gdb mycode




每调用一次函数其实就是在把函数的栈帧布局入栈。
我们可以利用bt来举行简朴地检察调用栈。



从上面两张图,我们看到,result是临时变量除了作用域Sum函数会斲丧,怎么还能把值给n?这是因为会先把值给寄存器,而我们说返回值具有常性也是因为这个寄存器无法修改。



我们把程序做一下反汇编:


在其中我们会看到如果我们的函数是有返回值的,每次函数调用完总是有这样一条mov
把eax寄存器的值mov到栈底寄存器加上偏移量里
栈底寄存器加上偏移量就是函数内部栈上的一个临时变量。
eax里放的就是函数的返回值。
我们可以看看Sum函数的反汇编里

return语句就是翻译成把rbp减4放到eax里。其实就是把返回值放到寄存器里。
然后未来再将通过寄存器把值写到返回值的变量里。
刚才那个寄存器加上偏移量就是main函数里的变量n


这条语句做了两件事。
call函数,然后将寄存器的值给变量n。
finish

我们可以在s进入调用的函数内部后输入finish直接竣事函数调用,回到原本的函数里:


此时正要做的是把寄存器的值给n。
p跟变量名
在这个时候我们举行p n,可以检察此时n里面的值:
可以发现是个随机值,然后我们再按一次n,也就是next,逐过程,然后再次p n会发现就酿成了函数返回值了。

断点禁用功能


断点可以被使能!
使之能,使之不能。
有时我们需要留下断点的陈迹。

这个Enb就是enable的意思。下面的y是yes的意思。
要注意的是,只有打断点时利用的是行号,接下来所有对断点的操作利用的都是编号。
disable 1就是将编号为1的断点禁用。

这样可以看到Enb下面酿成n也就是no了
再使能被禁用的断点,用的就是enable加编号

以上都只是一些基础命令,并没有涉及到真正的调试。

调试的本质

1.找到问题(最焦点)
2.检察代码上下文
3.解决问题
以是gdb的很多命令是帮我们找到问题的。

假如我们如今不知道代码在哪出错了,我们在20/25/30行各打了断点,也就是我们通过断点将代码分为了三大块。
然后我们按下r开始实行并调试,它就会来到第一个断点处停下。
而如果在这个过程中没有出错,就意味着这段代码区间并没有出错。
以是我们要再运行直到下一个断点,在VS中我们是按f5,那么在gdb中我们是再利用c命令,c是continue的缩写
它就会运行20-25行这段代码
以是,断点的本质是将代码举行块级别的划分。以是就可以以块为单位举行快速定位地区。


在通过s进入函数Sum后我们一直按n,一直在循环,但是我们如果确定了问题不在循环里但是又不想用finish直接走完该函数,那么怎么跳出循环呢?
我们也可以自由地跳转到指定行
until 行号

我们就可以跳到12行(前面的循环就实行完了)。
   (关于运行的指令)
  r是相当于f5,运行到第一个断点处停下来,再按f5是从头运行(会询问)
  c是运行接下来的代码直到下一个断点,continue (注意和r的区别)
  finish进入函数后直接走完这个函数退出来
  until是跳到指定行(把前面的实行完)
  s是逐语句调试
  n是逐过程调试
  长检察

我们用p可以检察对应的变量值大概内存,但是我们再按下n也就是接着往下调试时这些值不会跟着调试走:


那么怎么样才能长显示这些值,相当于在VS中打开监视窗口呢?
display
也可以带上取地点值,检察地点

可以发现我们每display一个值或地点,它就被打上了一个编号,然后当我们再次n的时候,它就按照编号倒序给我们显示了。
以是这个display我们就叫做检察上下文数据。
如果如今我们不想要某个值的监视,可以用undisplay,但是直接这样是不答应的:

而是要利用编号来undisplay
如果我们已经出了某个监视值的作用域,那么我们再n的时候,这个值就会自己消散了。
p直接盘算表达式
比如p 1+1+2:

检察一个函数内所有定义的临时变量

info locals

技巧

上面已经讲完了关于gdb基础的命令,接下来再讲一下关于gdb的几个技巧
1.watch

这个可以帮我们检察某个值的厘革,当厘革的时候就告诉我们

我们可以看到,会说是hardware watchpoint,也可以通过info b检察了

然后我们按n再继续调试,可以看到厘革的时候确实提醒我们了,会告诉我们老的值新的值。
调试技巧:

如果有一些值我们不盼望修改,就可以watch它,看是否是因为它厘革了导致的问题。
2.set var确定问题原因


假如如今我们已经找到了问题出在flag为0,但是我们不想回到源代码去修改再重新编译,可以直接在调试期间修改吗?
可以用set var flag=1

就直接把它改成1了
3.条件断点

一个断点我们可以删掉大概使不能来不让其触发,但若是我们既不想删也不想使之不能呢?
我们想让这个断点在某种条件下去触发。
比如我们想知道,当i=10,result的值是多少

我们在打这个条件断点时就要把条件带上:

b 13 if i == 10
然后info b也可以看到这个断点及其条件了

我们利用r从头调试,在第一个断点处停下后,我们此时按c就会来到我们打的条件断点处,此时我们p一下i的值看看,会发现就是10.
   要删除watch大概条件断点,都是一样的用d加编号(info b看到的那个编号)举行删除
  给已存在的断点新增触发条件


condition 4 i=20
我们就可以给我们的4号断点设置上条件,i=20的时候再停下来
   这个条件断点不如前几个常用。
  还有就是gdb不如cgdb试用。
  cgdb也有自己的一些语法,就像vim一样

如果cgdb中输入Esc再共同上下键,就可以翻阅我们的代码了
再按i就可以回到调试界面
这是cgdb的分屏操作
(有可能会卡死可能需要kill)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

鼠扑

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表