2011-05-27 20:19 290人阅读 评论(0) 收藏 举报

必先利其器之一:使用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)

使用PageHeap.EXE或GFlags.EXE检查内存越界错误 (转)的更多相关文章

  1. 使用PageHeap.EXE或GFlags.EXE检查内存越界错误

    必先利其器之一:使用PageHeap.EXE或GFlags.EXE检查内存越界错误 Article last modified on 2002-6-3 ------------------------ ...

  2. Windows下使用Gflags检查内存越界

    环境:windows xp. vs2005 Gflags可用于查找内存越界的问题. 访问一块申请的内存时,当访问的地址超过申请的范围时,就发生了内存越界的问题. 编写测试程序MemoryOverflo ...

  3. HSV做通道分离是出现的Vector内存越界错误

    vector<Mat> hsvSplit; //因为我们读取的是彩色图,直方图均衡化需要在HSV空间做 split(imgHSV, hsvSplit); equalizeHist(hsvS ...

  4. Windbg的gflags.exe -- Attach调试利器

    有没有碰到过程序启动就因为异常直接crash?有没有碰到程序启动之后什么反应也没有?有没有碰到过程序启动之后去触发另一个进程失败?有没有碰到别人的程序调用了你的代码,出现问题以后,让你来调查,而你只有 ...

  5. Android Monkey 脚本编写与检查内存泄露

    一.Monkey脚本编写 1.Monkey脚本格式 脚本优势: 简单快捷,不需要接触任何工具,只需要一个记事本文件 脚本缺点: 实现坐标.按键等基本操作的相应步骤,顺序脚本无逻辑性 脚本源码: \de ...

  6. 在64位windows下使用instsrv.exe和srvany.exe创建windows服务[转]

    本文转自:https://www.iflym.com/index.php/computer-use/201205020001.html 在32位的windows下,包括windows7,windows ...

  7. 在64位windows下使用instsrv.exe和srvany.exe创建windows服务

    在64位windows下使用instsrv.exe和srvany.exe创建windows服务   在32位的windows下,包括windows7,windows xp以及windows 2003, ...

  8. 【转】在64位windows下使用instsrv.exe和srvany.exe创建windows服务

    本文转自:https://www.iflym.com/index.php/computer-use/201205020001.html 在32位的windows下,包括windows7,windows ...

  9. Arduino上“Collect2.exe: error: ld returned 5 exit status”错误的解决方法

    1.运行环境 Windows xp; Arduino1.6.11 IDE. 2.问题 在Arduino编译时,经常出现如下的错误: collect2.exe: error: ld returned 5 ...

随机推荐

  1. Microsoft Visual Studio Web 创作组件安装失败的解决方法

    在网上查一下说是Office2007的问题.我把Office2007卸载了还是不行. 然后用Windows Install Clean Up工具清理,还是不行. 郁闷了.然后在安装包中的下面路径下找到 ...

  2. [转]linux 如何改变文件属性与权限

    转自:http://www.cnblogs.com/yangjinjin/p/3165076.html 我们知道档案权限对于一个系统的安全重要性,也知道档案的权限对于使用者与群组的相关性, 那如何修改 ...

  3. 从SVN导出指定版本号之间修改的文件(转)

    从SVN导出指定版本号之间修改的文件(转)   当一个网站项目进入运营维护阶段以后,不会再频繁地更新全部源文件到服务器,这个时间的修改大多是局部的,因此更新文件只需更新修改过的文件,其他没有修改过的文 ...

  4. Window Redis分布式部署方案 java

    Redis分布式部署方案 Window 1.    基本介绍 首先redis官方是没有提供window下的版本, 是window配合发布的.因现阶段项目需求,所以研究部署的是window版本的,其实都 ...

  5. Linux文件系统 (Ubunt)

    Linux 文件系统是linux的一个十分基础的知识,同时也是学习linux的必备知识. 本文将站在一个较高的视图来了解linux的文件系统,主要包括了linux磁盘分区和目录.挂载基本原理.文件存储 ...

  6. hadoop2.5.2学习及实践笔记(二)—— 编译源代码及导入源码至eclipse

    生产环境中hadoop一般会选择64位版本,官方下载的hadoop安装包中的native库是32位的,因此运行64位版本时,需要自己编译64位的native库,并替换掉自带native库. 源码包下的 ...

  7. CDH4.1基于Quorum-based Journaling的NameNode HA

    几个星期前, Cloudera发布了CDH 4.1最新的更新版本,这是第一个真正意义上的独立高可用性HDFS NameNode的hadoop版本,不依赖于特殊的硬件或外部软件.这篇文章从开发者的角度来 ...

  8. geeksforgeeks@ Largest Number formed from an Array

    http://www.practice.geeksforgeeks.org/problem-page.php?pid=380 Largest Number formed from an Array G ...

  9. 转】Spark DataFrame小试牛刀

    原博文出自于: https://segmentfault.com/a/1190000002614456 感谢! 三月中旬,Spark发布了最新的1.3.0版本,其中最重要的变化,便是DataFrame ...

  10. 内存中的static、const实现形式

    最近在考虑下半年找工作的事情,看了不少面试题目,其中还是蛮有收获的,把基础好好复习了一遍.比如这个题目,static.const现形式,static和const类型的变量在写程序的时候也写了很多,不过 ...