今天调试一个bug,用pageheap解决,在此记录一下。
bug症状如下:
1:不确定性崩溃,用vs调试启动每次崩溃地点都在crt分配或者释放堆的位置2:崩溃时vs看到的调用栈可能不同3:output输出HEAP:FreeHeapblock388c58modifiedat388c88afteritwasfreed
问题分析:
根据vs的输出,确定问题是在一块堆上分配的内存在释放后被改写了。由于CRT只能在下次做堆操作检查时才会暴露出问题,所以程序崩溃的调用栈是不确定的。折腾了2个小时后,启用pageheap缩小了程序出错到崩溃之间的距离,解决了问题。过程如下:1:启动pageheappageheap/enablemybug.exe0x012:调试启动mybug.exe现在程序崩溃的调用栈每次都相同,并且都在相同的线程中,根据调用栈信息很轻松的锁定了bug。
由于上面的例子过于复杂,下面写了一些小程序分析了pageheap的原理
char*buffer=newchar;???????//1buffer=0;?????????????????????//2delete[]buffer;???????????????????//3
这是一个很简单的堆内存越界的例子,在未启动pageheap的情况下,我们来看看buffer的内存情况:buffer=0x00388C80第一行执行后,buffer的内存
0x00388C80?cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd??................0x00388C90?cdcdcdfdfdfdfdababababababababfe?................
简单说明一下,调试模式下堆上未初始化的内存为cd,并且在内存结束处有4个fd的边界,用于debug模式下crt做内存检查,执行第2行之后,buffer的内存为
0x00388C80?cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd?................0x00388C90?cdcdcd00fdfdfdababababababababfe?................
可以看到4个fd的内存边界中第一个fd被破坏了。但这个时候程序并没有崩溃,继续执行第3行,程序崩溃,提示堆错误,可以看到,如果第2行和第3行之间有很长的代码逻辑,那么也只能在第3行执行之后程序才会崩溃。这给调式程序带来了极大的不便。如果第2行改为:buffer=0程序同样不会崩溃如果启用了pageheap,再来看看在debug模式下buffer的内存分配情况:第一行分配内存后,buffer的内存情况:
0x01675FE8?cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd?................0x01675FF8?cdcdcdfdfdfdfdd0?????????????????................
可以看到,和上面一样,在内存结束加上了4个fd的边界,d0是用于填补4字节对齐,注意buffer后面的地址(第一个??)为0x01675FF8+8=0x01676000,这是一个4k对齐的PAGE_NOACCESS页面,这个时候我们执行第2行代码buffer=0;同样不会崩溃,即使是修改buffer的值(4个fd边界和1个对齐d0),和未启动pageheap一样,程序都只会在执行第3行的时候崩溃。如果修改buffer则程序会崩溃。
通过这个例子,可以得出一个结论:启用pageheap后,堆内存分配在页面的末尾,后面紧跟了一个4k的PAGE_NOACCESS属性的页面,这种情况下,启用pageheap的好处是能在一定程度上检查内存越界。
再来看一个例子
char*buffer=newchar;?//1delete[]buffer;?????????????//2buffer=1;????????????????//3
这个例子演示了操作delete释放后的内存,在未启动pageheap的情况下,程序不会崩溃,原因同上一个例子,启用pageheap后,buffer内存为:第一行执行后:
0x01675FE8?cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd?................0x01675FF8?cdcdcdcdfdfdfdfd?????????????????................
第2行执行后:
0x01675FE8??????????????????????????????????................0x01675FF8??????????????????????????????????................
可以看到,启用pageheap后delete内存,分配该内存的整个页面都被设置为PAGE_NOACCESS属性,这样操作delete后的任何内存程序马上就会崩溃。
结论2:启用pageheap很容易检查操作delete后的内存的错误(包括2次delete)
总结:1:启用pageheap后,系统的堆管理器会把内存分配到4k页面的末尾(注意需要4字节对齐,debug模式下还存在边界检查的4字节fd)2:紧随着的下一个页面被设置为PAGE_NOACCESS属性3:启用pageheap后,释放内存把整个页面设置为PAGE_NOACCESS属性4:内存越界和非法操作依靠非法访问PAGE_NOACCESS属性的页面暴露问题5:由于每块内存都至少需要2个页面(1个页面分配,1个页面PAGE_NOACCESS),在内存消耗较大的环境下会占用极大的内存资源。6:把pageheap和crt的堆检查函数结合起来,能够更好的暴露堆相关bug
ps.pageheap的作用是在注册表位置HKLM/SOFTWARE/Microsoft/WindowsNT/CurrentVersion/ImageFileExecutionOptions下生成一个项
Tags:内存.
小编点评:SDelete-Gui文件永久删除.
下载小编点评:CAD是ComputerAidedDe.
下载小编点评:东日个人记事本是一款非常出色的记事本软件,
下载小编点评:2019年个税计算器是一款免费的个税计算工具.
下载小编点评:希望自己的电脑图标都有自己的特色吗?i.
下载小编点评:软件介绍TcpLogView一款Ni.
下载小编点评:软件介绍WDControl是一个非常便捷的.
下载小编点评:软件介绍天天万年历是一款最全面最实.
下载小编点评:爆炸吧果冻手游是一款卡通画面打造的休.
下载小编点评:腕龙模拟器普通版是一款画风非常真实的.
下载小编点评:pythagorea中文版是一款简.
下载小编点评:死亡跳跃最新版是一个非常具有魔性解压风格的.
下载小编点评:滑板公园3d游戏是一款非常好玩的滑.
下载一只球的旅行破解版下载-一只球的旅行中文破解版下载v1.1 安卓版
大大过山车手机版下载-大大过山车手游下载v1.0.1 安卓最新版
人偶背翻破解版下载-人偶背翻内购破解版游戏下载v1.0 安卓版
网络庞克手游下载-网络庞克手游官方版下载v8.0 安卓版
坑爹脑力游戏-坑爹脑力手游(暂未上线)v1.0 安卓版
公主换装舞会游戏下载-公主换装舞会手机版下载v15.2.3 安卓版
灵族杀app下载-灵族杀官方版下载v2.7.22 安卓版
首约特惠司机版app下载-首约特惠司机端下载v5.70.0.0002 安卓版
畅行高速app下载-畅行高速客户端下载v1.2.0 安卓版
猴子太疯狂中文版下载-猴子太疯狂最新版下载v3 安卓版
欢乐七彩瓶瓶消消乐无限金币版下载-欢乐七彩瓶瓶消消乐破解版下载v1.1 安卓内购版
SuperFilesKiller 文件清理
回转寿司店游戏手机版下载-回转寿司店正式版下载v1.1.12 安卓版