看流星社区

 找回密码
 注册账号
查看: 2112|回复: 0

VC诊断内存泄漏方法与技巧C++

[复制链接]

该用户从未签到

发表于 2015-3-27 11:49:46 | 显示全部楼层 |阅读模式
诊断内存介绍
      灵活自由是C/C++语言的一大特色,而这也为C/C++程序员出了一个难题。当程序越来越复杂时,内存的管理也会变得越加复杂,稍有不慎就会出现内存问题。内存泄漏是最常见的内存问题之一。内存泄漏如果不是很严重,在短时间内对程序不会有太大的影响,这也使得内存泄漏问题有很强的隐蔽性,不容易被发现。然而不管内存泄漏多么轻微,当程序长时间运行时,其破坏力是惊人的,从性能下降到内存耗尽,甚至会影响到其它程序的正常运行。另外内存问题的一个共同特点是,内存问题本身并不会有很明显的现象,当有异常现象出现时已时过境迁,其现场已非出现问题时的现场了,这给调试内存问题带来了很大的难度。掌握几种内存泄漏检测方法与技巧是非常重要的,不仅有利于你的日常工作,同时也对自己的代码质量有一定的提高。

普通程序内存泄漏
     Visual Leak Detector是一款用于Visual C++的免费的内存泄露检测工具。相比较其它的内存泄露检测工具,它在检测到内存泄漏的同时,还具有如下特点:
1、 可以得到内存泄漏点的调用堆栈,如果可以的话,还可以得到其所在文件及行号;
2、 可以得到泄漏内存的完整数据;
3、 可以设置内存泄漏报告的级别;
4、 它是一个已经打包的lib,使用时无须编译它的源代码。而对于使用者自己的代码,也只需要做很小的改动;
5、 他的源代码使用GNU许可发布,并有详尽的文档及注释。对于想深入了解堆内存管理的读者,是一个不错的选择。

      可见,从使用角度来讲,Visual Leak Detector简单易用,对于使用者自己的代码,唯一的修改是#include Visual Leak Detector的头文件后正常运行自己的程序,就可以发现内存问题。从研究的角度来讲,如果深入Visual Leak Detector源代码,可以学习到堆内存分配与释放的原理、内存泄漏检测的原理及内存操作的常用技巧等。
     首先将介绍Visual Leak Detector的使用方法与步骤,然后再一起初步的研究Visual Leak Detector的源代码,去了解Visual Leak Detector的工作原理。
使用Visual Leak Detector(1.0)。下面让我们来介绍如何使用这个小巧的工具,不过这个工具只适合于debug程序。
      首先从网站上下载zip包,解压之后得到vld.h, vldapi.h, vld.lib, vldmt.lib, vldmtdll.lib, dbghelp.dll等文件。将.h文件拷贝到Visual C++的默认include目录下,将.lib文件拷贝到Visual C++的默认lib目录下,便安装完成了。因为版本问题,如果使用windows 2000或者以前的版本,需要将dbghelp.dll拷贝到你的程序的运行目录下,或其他可以引用到的目录。
      接下来需要将其加入到自己的代码中。方法很简单,只要在包含入口函数的.cpp文件中包含vld.h就可以。如果这个cpp文件包含了stdafx.h,则将包含vld.h的语句放在stdafx.h的包含语句之后,否则放在最前面。下面通过一个简单的示例程序:
#include "stdafx.h"
#include <vld.h>
void func();
int main(int argc, char* argv[])
{
         printf("Hello World!\n");
          func();
          return 0;
}
void func()
{
          int *p = new int(0x12345678);
          printf("p=%08x, ", p);
}
在Visual C++的Output窗口得到:
Visual Leak Detector Version 1.0 installed (single-threaded static).
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 45 at 0x00920070: 4 bytes ----------         
/*54号内存块0x00920070地址泄漏了4个 bytes*/
  Call Stack:
    D:\coo\coo.cpp (16): func                       /*func函数在cpp 16行被调用*/
    D:\coo\coo.cpp (12): main                       /*双击查看func被调用的位置*/
    crt0.c (206): mainCRTStartup
    0x7C817067 (File and line number not available): RegisterWaitForInputIdle
  Data:
    78 56 34 12                                             xV4..... ........
Visual Leak Detector detected 1 memory leak.
Visual Leak Detector is now exiting.
The thread 0xD1C has exited with code 0 (0x0).
The program 'D:\coo\Debug\coo.exe' has exited with code 0 (0x0).
可以查看func内或者查看16代码行处,有无内存处理,并分析内存泄漏的原因。
内核程序内存泄漏
工作中有时会遇到内核级的内存泄漏,如果出现这个级别的内存泄漏,估计上述介绍的方法就无能为力了。幸好微软给我们程序员提供了一很强大的技术支持工具箱,而在这个工具箱中有一个工具poolmon.exe可以监视内存泄漏,包括内核级别的内存泄漏。下面开始介绍这个工具。
这个工具可以监视内存中总共使用的页面数和非页面的"内存池",以探测内存中有无"空洞"存在.内存中的所谓"空洞"是指:本来可供使用、但实际上并未使用的区域.减少空洞可以提高内存的使用效率,防止内存的浪费.与使用别的命令行程序不同,这个程序需要在加载运行之后才可以得到"在线"的提示帮助信息.另外,这个工具还需要一个叫做gflags的程序来配合,更麻烦的是程序gflags也像前面介绍的有些程序一样,具有适应两种环境的版本.这种互相交叉的用法使得不熟悉它们相互关系的人感到眼花缭乱.下面结合Poolmon.exe的使用,对二者都先介绍命令行的版本.
1、 在使用Poolmon.exe之前,必须先运行gflags.可以在“开始->运行”中键入cmd,点击确定打开命令行窗口,(注意:本文中所有命令行程序都可以先用cmd打开一个类似dos模式的窗口),然后在窗口中键入命令和参数,执行该命令行程序:gflags -r +ptg 参数的含义到介绍gflags的GUI版本时再解释.
2、 执行后重新启动计算机.
3、 重新启动成功后,即可在命令行中执行 poolmon
运行poolmon工具后,可以查看系统内内存池的使用情况(包括分页内存和非分页内存),还可以通过很多命令进行poolmon的操作。
下面介绍几种关键的poolmon命令及标签项含义。
1. 使能Tag模式
在使用poolmon之前,你必须使能Tag模式并重新启动服务器。池Tag的特性是将收集和计算的信息通过分配内存的Tag值进行排序,重新启动计算机。
注:使用Windows 2003服务器不需要使能Tag,它是Windows 2003的默认值
使用Gflags.exe工具
运行Gflags.exe工具选择Enable Pool Tagging
2. 使用poolmon.exe工具收集信息
Poolmon常用命令如下:
P- 切换显示未分页或显示已分页或两者都显示
   L - 切换是否高亮显示值有变化的行
   E- 在数据的底部显示池合计值
   H/? - 帮助
   Q- 退出
   T- 按Tag名排序
   A-按分配尺寸排序
   F- 按空闲尺寸排序
   D- 按分配和空闲的差排序
   B- 按使用字节排序
   M -按分配字节排序
列说明含义:
Tag:    池分配的4字节Tag
Type:   分页或未分页
Allocs: 所有分配的计数
Frees:  所有空闲的计数
Diff:(Allocs - Frees)
Bytes:池消耗的合计字节数
Per Alloc:(Bytes/Diff)
示例如下:
想要查看tag:CM22的内存使用情况,且查看CM22是属于哪个文件内的,可以使用findstr查看CM22,可以通过cmd工具输入如下一条语句:
findstr /s /m /l "CM22" c:\windows\system32\drivers\*.sys
C:\Documents and Settings\wang_hui> findstr /s /m /l "CM22" c:\windows\system32\drivers\*.sys
c:\windows\system32\drivers\ ShdPci.sys
如果要查找CM22内存泄漏的具体位置或是什么原因导致的内存泄漏可以通过查看分析源代码即可找到问题所在。
可以通过在上述ShdPci.sys源代码中查找标记号CM22的具体位置。从而定位到代码行。之后就要根据你代码内容分析问题了……
以上就是介绍监视内存泄漏的方法与技巧。
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-4-18 09:54

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表