您的位置:首页 > 其它

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

2011-06-23 16:40 531 查看
打开检查功能:



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%

立即发现

访问块结尾之后的内容

在释放后发现

立即发现

访问块开始之前的内容

在释放后发现

立即发现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: