gflags 检查内存越界

使用gflags 检查内存越界

什么是Page Heap(页堆)?

     从Windows 2000 开始操作系统开始在堆管理器引入“校验层”,即Page Heap管理器。这个校验层处于Ntdll.dll模块内。可以验证应用程序所有的动态内存操作(读写、分配、释放及其它操作)。

页堆有两种类型:正常页堆和完全页堆(Full Page Heap)

完全页堆:

     当分配一块内存时,通过调整内存块的分配位置,使其结尾恰好与系统分页边界对齐,然后在边界处再多分配一个不可访问的页作为保护区域。这样,一旦出现内存读/写越界时,进程就会Crash,从而帮助及时检查内存越界。

因为每次分配的内存都要以这种形式布局,尤其对于小片的内存分配,即使分配一个字节,也要分配一个内存页,和一个保留的虚拟内存页(注意在目前的实现中,这个用作边界保护区域的页从来不会被提交)。这就需要大量的内存,到底一个进程需要多少内存,很难估算,因此在使用Page Heap前,至少保证你的机器至少设置了1G虚拟内存以上。

正常页堆

     正常页堆原理与CRT调试内存分配函数类似,通过分配少量的填充信息,在释放内存块时检查填充区域。来检测内存是否被损坏,此方法的优点是极大的减少了内存耗用量。缺点是只能在释放块时检测,不太好跟踪出错的代码位置。

GFlags、AppVerifier、Pageheap.exe

     GFlags、AppVerifier、Pageheap.exe是三种外壳工具,都是用来方便用户配置Page heap 选项的。Page Heap选项位于注册表目录:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\你的可执行程序名\。当Windows开始启动一个进程时,Window通过检查这个注册表目录的设置,对该进程应用相应的PageHeap选项。

Pageheap.exe

- PageHeap配置工具,在Windows 2000 Professional SP2 以上可用。已经被GFlags取代。

GFlags

-老牌的PageHeap配置工具,有命令行和GUI两种操作方式,功能比较全,包含在Windbg调试器安装包内。同样在Windows 2000 Professional SP2 以上可用。

AppVerifier

-新的PageHeap配置工具,需要XP系统才支持。VS2005内置了AppVerifier,支持,用“Debug”菜单—〉“Start With Application Verifier”启动程序,会自动启动Page Heap。下载:http://www.microsoft.com/downloads/details.aspx?FamilyID=bd02c19c-1250-433c-8c1b-2619bd93b3a2&displaylang=en#filelist

一些使用GFlags命令行的例子:

配置正常页堆:

"C:\Program Files\Debugging Tools for Windows (x86)\gflags.exe" /p /enable qq.exe

配置完全页堆:

"C:\Program Files\Debugging Tools for Windows (x86)\gflags.exe" /p /enable qq.exe /full

列出当前启动了页堆的进程列表:

"C:\Program Files\Debugging Tools for Windows (x86)\gflags.exe" /p

取消页堆设置:

"C:\Program Files\Debugging Tools for Windows (x86)\gflags.exe" /p /disable qq.exe

一定需要这些工具吗?

正如前面提到的,PageHeap属于操作系统提供的功能,这几个工具只是方便修改注册表中的选项,在实际应用中可以通过直接修改注册表来启用PageHeap。这在客户的机器上很有用,不再要求客户去安装这些软件。

一些特殊选项解释:

/unaligned

这个选项只能用于完全页堆。当我们从普通堆管理器分配一块内存时,内存总是8字节对齐的,页堆默认情况下也会使用这个对齐规则,但是这会导致分配的内存块的结尾不能跟页边界精确对齐,可能存在0-7个字节的间隙,显然,对位于间隙范围内的访问是不会被立即发现。更准确的说,读操作将永远不能被发现,写操作则要等到内存块释放时校验间隙空间内的填充信息时才发现。/unaligned用于修正这个缺陷,它指定页堆管理器不必遵守8字节对齐规则,保证内存块尾部精确对齐页边界。

需要注意的是,一些程序启用这个选项可能出现异常,例如IE和QQ就不支持。

/backwards

这个选项只能用于完全页堆。这个选项使得分配的内存块头部与页边界对齐(而不是尾部与边界对齐),通过这个选项来检查头部的访问越界。

/debug

指定一启动进程即Attach到调试器,对于那些不能自动生成dump的程序,是比较有用的选项。

页堆能校验的有效范围

     所有内存分配函数,只要最终调用到ntdll.Dll堆管理函数(即RtlAllocateHeap,RtlFreeHeap),页堆都是有效的。具体包括:

诸如 HeapAlloc、HeapFree、HeapReAlloc、LocalAlloc、LocalFree、LocalReAlloc 等等Kernel32提供的堆管理函数。

CRT内存分配如:malloc、free、realloc、msize、expand、运算符 new、delete、new[ ]、delete[ ]等等。

但页堆不能用于验证虚拟内存分配函数如:VirtualAlloc、VirtualFree等分配的内存块。

 

页堆能处理的错误类型:

错误类型                                                 正常页堆                                整页堆 

堆句柄无效                                             立即发现                                立即发现 

堆内存块指针无效                                 立即发现                                立即发现 

多线程访问堆不同步                             立即发现                                立即发现 

假设重新分配返回相同地址(realloc)   90% 内存释放后发现            90% 立即发现

内存块重复释放                                     90% 立即发现                       90% 立即发现 

访问已释放的内存块                             90% 在实际释放后发现       90% 立即发现 

访问块结尾之后的内容                         在释放后发现                       立即发现 

访问块开始之前的内容                      在释放后发现                       立即发现

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值