天天看点

堆破坏(Heap Corruption)和Gflags什么是Heap CorruptionHeap Corruption的危害PageHeap检测Heap Corruption的原理PageHeap的使用方法其他相关工具写程序过程中预防Heap Corruption

什么是Heap Corruption

 堆破坏是内存破坏的一种,简单来说就是由于程序的错误导致堆内存被意外改写,典型的情况包括:

  1. 申请了N个Bytes的内存,却试图写入> N个Bytes的内容;
  2. 向已经释放的内存位置写入内容;

fFrameSize = pSearch01To - fpBuffer;    // 在某种情况下会出现fFrameSize = 0xFFFFFFFC

memcpy(fTo, fpBuffer, fFrameSize);      // 这里memcpy会发生什么?

Heap Corruption的危害

把不属于自己的内存块的内容改写掉,危害是很显然的。更要命的是,Heap Corruption的问题往往很难排查,因为:

  1. 每次运行表现出来的现象可能不一样;
  2. Debug版和Release版表现可能不一样;
  3. 问题暴露的地方和问题引入的地方可能相差很远,两者逻辑上没有必然联系;

PageHeap检测Heap Corruption的原理

PageHeap工具可以在运行时检测Heap Corruption,其基本原理是在我们分配的内存块前后加上一些额外信息,这些额外信息用以检测是否出现越界写的情况。PageHeap分为Full模式和Normal模式:

  1. Full模式:在我们分配的每个内存块尾上加一页non-accessible page。Full模式的好处是“Sudden Death”,即在问题发生的点上立马Access Violation,易于Debugging。坏处是大量消耗内存。
  1. Normal模式:在我们分配的每个内存块前后加少量的填充字段。Normal模式的好处是内存消耗较少。坏处是只有在释放内存时才会检测出Heap Corruption,Debugging难度还是比较大。

PageHeap的使用方法

大家在WinDbg的安装路径下,可以看到gflags.exe这个工具,gflags集成了pageheap的功能。Gflags可以以GUI方式或Console方式运行,但是GUI方式只能启用PageHeap的Full模式,所以建议大家通过Console方式来使用gflags(以Run As Administrator方式打开Cmd窗口运行gflags)。

几条基本命令如下:

Gflags.exe /p /enable dest.exe

Gflags.exe /p /disable dest.exe

Gflags.exe /p

具体使用方法可以在WinDbg的帮助文档中搜索PageHeap,或在命令行模式下gflags /p /?

其他相关工具

除了gflags\pageheap之外,Application Verifier也可以用来检测Heap Corruption问题。Application Verifier也包含了其他很多运行时检查项,大家可以在工作中按需使用。Application Verifier的问题是它不支持托管代码。

写程序过程中预防Heap Corruption

PageHeap、Application Verifier或其他的运行时检查工具其实都是事后诸葛亮;对我们来说更重要的是在每天写程序的过程中就控制住,不给Heap Corruption机会。控制方法不止一种,就我们目前的情况来说,有两点是可以立即做的:

  1. Klocwork静态代码检查:Klocwork不能帮我们查出所有的Heap Corruption,但实践证明还是能查出一部分的;
  2. 使用安全的函数:就是xxx_s,如memcpy_s等;对于我们自己写的涉及内存操作的函数,也应设计成安全的。

继续阅读