Using GDB to debug
记一次使用GDB查问题的过程
1. 背景
void ModuleMgr::OnFinish(int result)
{
for(int i = 0; i < vAppList.size(); i++)
{
vAppList[i]->Finish();
}
}
最近项目中碰到一个问题:在一个list
中有多个对象,当其中一个对象调用了一系列函数后,其后续对象并不能按照预想继续执行,而是直接退出了函数。具体从以上代码来看,appList
里有两个对象:obj_1
和obj_2
,当obj_1
调用其成员函数Finish()
后,obj_2
并不能正常继续调用其自己的Finish()
函数,而是直接退出了循环。从表现上看,像是obj_1
在执行自己的逻辑的时候,把appList
的内存写坏了。一般情况下,这种现象都是因为数组的越界操作从而导致写坏内存引起。所以,我们尝试使用GDB来进行Debug,找到真正出问题的地方。
2. 过程
因为之前我们推测有可能是obj_1
把其后续内存写乱了,但是也有可能直接把List
的结构给弄坏了,所以在GDB的时候我们不仅要关注obj_2
的地址,还需要关注这个list
本身的结构有没有变化。因为从逻辑上看,这个列表里的内容不应该在这里改变。
1. 断点到该位置,查看需要关注的变量
结合我们之前的推测,我们需要看这个obj_1
和obj_2
的地址有没有发生改变,以及list
本身的结构是否发生了改变。又通过GDB的ptype
(可以查看具体类型)得知list
其实是vector
,也就是说其结构中包括start
和finish
两个指针。所以,先打印出这四个值:
从图中可看到,vAppList
中有两个元素obj_1
和obj_2
,其地址也分别打印了出来。同时,vAppList
的start
和finish
指针的值也分别打印了出来。因为我们怀疑这四个值可能被修改了,所以可以通过watch
指令来看是否发生了改变,以及发生了改变时的具体的值。我们也可以首先自己断点到obj_1
的Finish()
代码中单步调试,看看是执行到那里,导致这四个值发生了改变。
如图,通过单步调试,以及GDB中的f 1
命令跳到上一层函数context中,我们可以看到在执行了obj_1
的Finish
函数时,vAppList
的start
和finish
值发生了改变。也就是说,vAppList
的结构发行了变化,size
也因此变为了0。
2. 监视变量
可见,确实是obj_1
内部的Finish()
函数中的某一段导致了vAppList
的结构发生了变化。通常来说,这种情况都是因为操作到了不正确的内存块。最常见的情况就是数组越界,导致操作了其他的内存。但是具体是哪一行代码出错我们现在并不知道,但是可以通过watch vAppList._M_impl._M_Start
来监视start
指针,一旦该指针发生了变化,则会打印出此时具体的行号。(这里需要注意start
和finish
不能同时watch,我也不知道为什么)。
从图上可以看到,watch
指令直接将start
指针的变化打印了出来,其值从0x68476a0
变为了0x0
。也就是说,在Monitor
这个文件的1978行,将vAppList
的结构进行了非法赋值。去查看代码可知,里面确实有一处数组越界操作,有可能操作到这一块内存。
3. 总结
在使用GDB查问题时,最好是先根据问题的表现推测是什么原因才可能导致出现这样的现象。然后,通过断点和监视来找到确切的代码段。像类似的内存非法修改的问题,其实是一个确定的问题。也就是说,每次非法修改时,其偏移量都是固定的。换句话说,这个问题是可复现的问题,相对没那么复杂。
当时还看了出问题代码文件的最近一段时间的修改记录,发现这个越界以前其实也早就存在。但是一直没出现问题,而是最近才导致问题。这很有可能是因为obj_1
的内存布局一直在变化(因为代码一直在修改)。以前可能也有非法修改内存,但是并没有踩到重要的地方,所以没出现明显的问题。但是这次,刚好obj_1
这个类的修改,导致其内存布局发生了改变,也就是说刚好这次越界就踩到了vAppList
那一块的内存。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 gzrjzcx@qq.com
文章标题:Using GDB to debug
文章字数:1.2k
本文作者:Alex Zou
发布时间:2021-05-02, 20:55:55
最后更新:2024-07-10, 03:02:36
原始链接:https://www.hellscript.cc/2021/05/02/subposts_notes/Using-GDB-to-debug/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。