今天调试一个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:内存.
小编点评:操作:将takeown.exe复制.
下载小编点评:美速美速度的护眼宝纯净版(过滤蓝光护眼)是.
下载小编点评:教你学维语电脑版是新疆青少年出版社.
下载小编点评:音标是英语的基础,就像我们学汉语要先学拼音.
下载小编点评:软件介绍华琦库管精灵是我们推出的一.
下载小编点评:软件介绍MLangStudio支持多语言.
下载小编点评:软件介绍如果你是软件工程师或是软件产品.
下载小编点评:软件介绍网页开发大师可以建立普通网.
下载小编点评:软件介绍微软官方主题包.包含多张精.
下载小编点评:软件介绍MySQL开发是一个多功能的Windo.
下载小编点评:软件介绍WebLogExplore.
下载小编点评:软件介绍黑色透明Transblac.
下载小编点评:软件介绍FreeEIM是一款免费的.
下载lllc官方版下载-lllcapp下载v1.7.3 安卓版
英魂之刃战略版内测版下载-英魂之刃战略版体验服下载v2.2.5.0 安卓版
Bootzilla
事务日志管理NetWrix Event Log Manager
APP分享应用市场下载最新版-app分享软件(appshare.apk)下载v3.1.5.2 安卓版
文件md5修改器app下载-文件md5修改器手机版下载v1.4.5 安卓版
play max下载安装-playmax软件下载v1.1.98.1 安卓版
腾势app官方下载-腾势平台(DENZA)下载v4.0.2 安卓版
阿原智能最新版下载-阿原智能app下载v1.1.1 安卓版
小森林最新版下载-小森林ai绘画app下载v1.0.1 安卓版
视频压缩大师app下载-手机视频压缩大师软件下载v1.1.0 安卓版
nfc复制门禁卡软件下载-nfc复制门禁卡app下载v1.1 安卓版
镜花缘九游版下载-九游镜花缘官方版下载v8.0.0.1 安卓版