zoukankan      html  css  js  c++  java
  • 使用PageHeap.EXE或GFlags.EXE检查内存越界错误 (转)

     

    必先利其器之一:使用PageHeap.EXE或GFlags.EXE检查内存越界错误
      Article last modified on 2002-6-3
      ----------------------------------------------------------------
      The information in this article applies to:
      - Microsoft Visual C++, 32-bit Editions, version 6.0, SP5
      ----------------------------------------------------------------
      我推荐使用PageHeap.Exe和Gflags.Exe,主要的原因还是因为当有人问内存越界的错误如何查出来的时候,国外的朋友经常会推荐这两个工具(highly recommend)。我用过之后,也觉得有些时候用用还是有好处的。
      
      PageHeap.Exe将针对某个指定的应用程序启用Page Heap标志,从而自动监视所有的malloc、new和heapAlloc的内存分配,找出内存错误。
      PageHeap.Exe的下载地点:
    http://support.microsoft.com/default.aspx?scid=http://download.microsoft.com/download/vc60pro/Utility/6.0/WIN98/EN-US/PageHeap1.exe
      下面我们简单地给出PageHeap使用步骤:
      第一步:
      在命令行中运行PageHeap.Exe。如果你以前设置过启用Global Page Heap标志,那么你将看到一个列表,给出所有已经启用了的应用程序的名字,不含路径。
      如下所示:
      C:/>pageheap
      pgh.exe enabled
      testSplit.exe enabled
      第二步:
      编译一个小程序,其中有如下代码:
      void main()
      {
       int m_len = 5;
       char *m_p = (char *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, m_len);
       m_p[m_len] = 0;
      
       HeapFree (GetProcessHeap (),0, m_p);
      }
      Build出一个Debug版本。运行之,你看不到有任何异常的报告。
      但其实m_p[m_len]=0这句话就是越界写了,因为只分配到了m_p[m_len-1]!这种情况就叫Dynamic memory overrun。用BoundsChecker是可以查到的。
      这时,表面上看不出任何问题,但是一颗定时炸弹已经埋下了。
      第三步:
      在命令行中运行PageHeap /enable YourApplicationName.exe 0x01。
      再运行一次不带参数的PageHeap,察看上面的命令是否生效。你的应用程序应该在启用的列表中。
      注意:千万不要在YourApplication.Exe前面加上路径!!
      0x01的含义在后面说明。
      第四步:
      再次运行你的程序。
      你将会注意到在Output窗口的加载各种DLL之前,多了几句话:
      Loaded exports for 'C:/WINNT/System32/ntdll.dll'
      Page heap: process 0x57C created heap @ 00130000 (00230000, flags 0x1)
      Loaded 'C:/WINNT/system32/MFC42D.DLL', no matching symbolic information found.
      ..
      Loaded 'C:/WINNT/system32/MSVCP60D.DLL', no matching symbolic information found.
      Page heap: process 0x57C created heap @ 00470000 (00570000, flags 0x1)
      Loaded exports for 'C:/WINNT/system32/imm32.dll'
      这就是Page Heap的监视机制在发挥作用!他告诉你你的堆00470000被创建出来了。
      然后程序退出后,Output窗口有这么几句话表明一定有什么错误发生了:
      Page heap: block @ 0015AFF8 is corrupted (reason 10)
      Page heap: reason: corrupted suffix pattern
      Page heap: process 0x57C destroyed heap @ 00471000 (00570000)
      The thread 0x8A8 has exited with code 0 (0x0).
      这说明在销毁堆00470000时遇到了麻烦,就是数据块0015AFF8被误用了,原因是误用了下标语法。看,说得多么清楚!也节省了许多翻来覆去查代码的工作!
      PageHeap的使用中有几点值得注意:
      1:启用PageHeap不能够影响正在运行中的应用程序。如果你需要启用一些正在运行且不能重启的程序的PageHeap,那请运行PageHeap启用后,重新启动机器。
      2:要想查看PageHeap把信息放到哪里了,请打开你的注册表,来到
       /HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT
      /CurrentVersion/Image File Execution Options
      你将会看到你的应用程序也在这个项下面。你的应用程序的GlobalFlag被设置为了0x02000000,PageHeapFlags被设置为了0x01。
       3:PageHeap的原理是这样,它在已分配的内存的后面放上几个守护字节(Guard Bytes),再跟上一个标记为PAGE_NOACCESS的内存页。这样,已分配内存的后面如果被重写了,那么守护字节就会被改变,于是当内存被释放 时,PageHeap就会引发一个AV(Access Violation)。大体上就是这样。所以只有最后释放这块问题内存时,才会有PageHeap的报告!这就是PageHeap的局限性吧。
      参数0x01的含义:
      FLAGS hex value (0x...) has the following structure:
       B7-B0 Bit flags 1 - enable page heap
       01 - enable page heap. If zero normal heap is used.
       In 99% of the cases you will want this to be set.
       02 - collect stack traces (default on checked builds)
       04 - minimize memory impact
       08 - minimize randomly(1)/based on size range(0)
       10 - catch backward overruns
      看到了吗?你还可以设置参数为0x10,从而可以检查内存向前的越界写!
       Gflags.Exe是微软的Debugging Tools里面的工具。在Windows 2000的Resource Kit中也可以找得到。我们也可以用它来完成和PageHeap相同的任务。当然,Gflags.EXE还能做许许多多其他的事情。这里我们就不介绍了, 总之物超所值。
      具体的使用办法是:
      1) 运行Gflags.Exe;
      2) 你将看到一个对话框。在”Image File”的编辑框中写下你的应用程序的名字,如YourApp.Exe。注意不要路径!
      3) 选择”Image File Options”的单选钮;
      4) 这时,你会看到对话框的内容突然一变。选中“Place heap
      allocations at ends of pages”前的复选框。
      5) 点击Apply按钮。
      这样,就达到了PageHeap的效果。现在运行你的程序,overwrite你的堆,就应该生成一个AV了!
      (预知详情请收听微软KB:SAMPLE: PageHeap1.exe Finds Heap Corruption and Memory Errors (Q264471) 你可以按照这篇文档所指引的步骤学习如何使用PageHeap)

  • 相关阅读:
    c语言中 fgetc函数、fputc函数实现文件的复制
    c语言 13-7 利用fgetc函数输出文件的字符数
    c语言 13-6 利用fgetc函数输出文件的行数
    c语言中fgetc函数:显示文件内容
    c语言 13-5
    c语言 获取程序上一次运行时间的程序
    hzwer模拟赛 虫洞
    LYDSY热身赛 escape
    bzoj2330 糖果
    繁华模拟赛 Vicent坐电梯
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/4097763.html
Copyright © 2011-2022 走看看