GFlags 检查内存越界、野指针等作用的工具使用

转载于:http://blog.csdn.net/zhufangyou/article/details/6563878

 

打开检查功能: gflags /p /enable  **.exe /full

关闭检查功能: gflags /p /disable  **.exe

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

1. 案例

调试运行,程序退出时崩溃在 ntdll 中的一个函数中, output 窗口中输出:
HEAP: Free Heap block xxxxxx modified at xxxxxx after it was freed

此时,无法快速找出程序哪里出现了内存非法访问。

2. 解决方法

a. 安装 Debugging Tools for Windows( 也就是 WinDbg) ,安装后将安装目录添加到 Path 环境变量中

b.
执行: gflags -p /enable ***.exe /full
"***.exe"
为需要调试的程序名称,不需要完整路径。
该命令行会在注册表里设置一些调试参数 , 使内存在使用的时候加入了保护机制 , 一旦内存写
越界 , 或者发生野指针的问题 , 都会导致一个中断。由此 , 就可以确定问题到底出在哪里了。 |

配置正常页堆:

"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


c.
调试运行自己的程序,此时 Visual C++ 会直接定位在有问题的代码处。

d.
删除注册表中的调试设置: gflags -p /disable ***.exe

 

什么是 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 命令行的例子:

一定需要这些工具吗?

正如前面提到的, 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、付费专栏及课程。

余额充值