软件调试系列:崩溃篇之内存值异常

    本来想尽快写一系列文章来介绍各种常见缺陷的软件调试文章,但由于工作原因并且大家的反映似乎不太好,所以我也有点偷懒了。不管怎么样,正好现在有空,咱来聊一聊最近我查的一个崩溃BUG吧。

前几天接手排查一个崩溃BUG,测试部报告说该BUG在两台电脑上出现过,并且错误提示信息一模一样,这个BUG直接原因很容易定位,通过windbg分析该BUGdump文件发现,程序在释放内存时出错,其调用栈如下图1所示:

图1

发现该线程在释放内存时出错,弹出了一个MessageBox提示窗,那么先查看一下错误提示信息是什么吧?如图2所示

 

图2

Dbgheap.c line 1050行的代码正是下图中高亮标记的代码;

图3

按照贯例,先检查一下pHead->nBlockUse的值是什么?

 

图4

发现nBlockUse值为59,正常情况下该值为1,因此没法通过断言判断_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse))

那么到此为止,我们已经找到了导致软件崩溃的直接原因,但革命尚未成功,同志们仍需努力,现在nBlockUse值为什么会由1变成59,是现在我们急需解答的问题。

是的,这个问题,很难回答,但却别无办法,对于这类问题的排查,我们只有一个办法,即提出假设进而验证,再推翻假设,再提出假设进行验证,周而复始,至之找到问题的答案;

对于上面提到的个问题,目前有6个假设

1:内存被重复释放

2.多线程同时读写访问引起内存写值异常问题

3.:内存溢出

4.:被野指无意篡改值

5.内存条上的存储单元存取发生异常

6软件病毒引起

假设一 内存被重复释放

该假设一经提出就被立即否决,理由有以下几点

A)_CrtMemBlockHeader记录的两向链表仍然有效,未被破坏

图5

B)待释放的内存154bfb20 的内容仍然有效:

图6

假设二:多线程同时读写访问引起内存写值异常问题。

这个假设比较靠谱,很多值异常问题确实是由于在多线程访问题未做同步保护引起,但在这个问题上却不适用,因为本软件是单线程程序,多线程访问冲突也就无从谈起了。

假设三:内存溢出

是的,内存溢出真的可能会引起这种情况,但是目前正在被释放的内存如下所示

图7

你看,用户数据区前后的 fdfdfdfd保护字段并没有被篡改,而异常的数据在第二行即54bfb08指向的内存,这有可能是用户区数据写下溢引起内存54bfb08被修改的问题吗?我不认为是这样的,如果是数据下溢,我则认为fdfdfdfd字段至少应该被修改了吧。

假设4:被野指无意篡改值

真的有这么巧吗?自问一百遍!

我觉得还真没有这么巧。

假设5内存条上的存储单元存取发生异常

以上4种假设都被一一排除,到验证这条假设时,基本已经黔驴技穷了。

但我坚信,排除所有不可能之后,剩下的那一个不管合不合理,它就应该是真相,好吧,我验证这一想,我使用了多款内存检测工具,MemtestWIN7自带内存检测工具对其进行检测,均未发现内存问题。

假设软件病毒引起?

好吧,无视这一条假设吧。

现在,所有可能想到的假设均被否定,但问题原因却还没有找到,那就只有两种可能,

1:还有其它的可能性,

2:某一假设可能被错误地否定了。

是否有其它的可能性,暂时想不到,但是回头看一下假设三被否决就显得有点证据不足了。

不同的人查看同一个Dump文件所能挖掘的信息是不一样的,一来是想法不一样,二来是经验不同,所以在排查这类疑难问题时,进行结对排查,是很有帮助的。

我一同事提出查看一上内存值是否合理。嗯,那我们就来看一下内存值

图8

以上是正在被释放的内存的内存值,有发现什么异常不?

仔细观察发现其中154bfb08的值居然后fdfdfdfd之后的用户区数据既然是相类似的。

图9

至此真相大白了,具体原因是这样的,154bfb20指向的是一个数组,数组中的每一个元素是一个40字节的结构体,结构体中的一个数据成员是SYSTEMTIME, 代码在操作该数组时,使用了-1 的下标索引将该对应的元素的SYSTEMTIME进行了赋值,正因为如此,才导致fdfdfdfd这个值没有被赋盖。

154bfb08处的时间值为:

图10

那么,你也知道了,排查崩溃类型的BUG一般步聚,就是猜测,验证,猜测,再验证,再无其它技巧可寻了。

整篇看完的朋友,留个影吧,也好让我知道写这个对多少朋友有用。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值