51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 18244|回复: 27
打印 上一主题 下一主题

内存泄漏检测

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2005-5-25 13:28:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我们现在在做一个项目用.net,遇到内存严重泄漏,都说.net能自动解决内存泄漏,但是我们这里内存以每秒>>100K的速度泄漏,已经泛滥成灾了。呵呵帮帮忙吧。或者谁知道哪里有.net内存泄漏测试工具可以下载,谢谢了先。
                                          我早上在别的版里发了但是没人回,不知道是不是发错地方了,发在这里也不知道对吗,错了版主别怪啊。谢谢

[[i] Last edited by songfun on 2005-5-31 at 21:18 [/i]]
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
  • TA的每日心情
    奋斗
    2018-2-28 18:04
  • 签到天数: 40 天

    连续签到: 1 天

    [LV.5]测试团长

    2#
    发表于 2005-5-26 10:23:34 | 只看该作者

    给份资料看下。

    内存泄漏检测(自己写的)  作者 很土
    关键字 内存泄漏 内存 Debug Heap 堆
    原作者姓名 很土
    文章原始出处 自己写的

    介绍
    简单说明了一下没有工具的情况如何运用VC库中的工具来检查代码的内存泄漏问题

    读者评分 8 评分次数 2

    正文
    内存泄漏检测

    一: 内存泄漏
    内存泄漏是编程中常常见到的一个问题. 内存泄漏往往会一种奇怪的方式来表现出来,基本上每个程序都表现出不同的方式. 但是一般最后的结果只有两个,一个是程序当掉.一个是系统内存不足. 还有一种就是比较介于中间的结果程序不会当,但是系统的反映时间明显降低,需要定时的Reboot才会正常.

    有一个很简单的办法来检查一个程序是否有内存泄漏.就是是用Windows的任务管理器(Task Manager).  运行程序,然后在任务管理器里面查看 “内存使用”和”虚拟内存大小”两项,当程序请求了它所需要的内存之后,如果虚拟内存还是持续的增长的话,就说明了这个程序有内存泄漏问题. 当然如果内存泄漏的数目非常的小,用这种方法可能要过很长时间才能看的出来.

    当然最简单的办法大概就是用CompuWare的BoundChecker 之类的工具来检测了,不过这些工具的价格对于个人来讲稍微有点奢侈了.

    如果是已经发布的程序,检查是否有内存泄漏是又费时又费力. 所以内存泄漏应该在Code的生成过程就要时刻进行检查.
    二: 原因
    而内存泄漏产生的原因一般是三种情况: 1.分配完内存之后忘了回收.2. 程序Code有问题,造成没有办法回收.3.某些API函数操作不正确,造成内存泄漏.
    1.    内存忘记回收,这个是不应该的事情.但是也是在代码种很常见的问题.分配内存之后,用完之后,就一定要回收. 如果不回收,那就造成了内存的泄漏,造成内存泄漏的Code如果被经常调用的话,那内存泄漏的数目就会越来越多的.从而影响整个系统的运行. 比如下面的代码
    for (int =0;I<100;I++)
    {
        Temp =  new BYTE[100];
    }
    就会产生 100*100Byte的内存泄漏.
    2.    在某些时候,因为代码上写的有问题,会导致某些内存想回收都收不回来,比如下面的代码
    Temp1 = new BYTE[100];
    Temp2 = new BYTE[100];
    Temp2 = Temp1;
    这样,Temp2的内存地址就丢掉了,而且永远都找不回了,这个时候Temp2的内存空间想回收都没有办法.

    3.    API函数应用不当,在Windows提供API函数里面有一些特殊的API,比如FormatMessage.  如果你给它参数中有FORMAT_MESSAGE_ALLOCATE_BUFFER,它会在函数内部New一块内存Buffer出来.但是这个buffer需要你调用LocalFree来释放. 如果你忘了,那就会产生内存泄漏.

    三: 检查方法

    一般的内存泄漏检查的确是很困难,但是也不是完全没有办法.如果你用VC的库来写东西的话,那么很幸运的是,你已经有了很多检查内存泄漏的工具,只是你想不想用的问题了. Visual C++的Debug版本的C运行库(C Runtime Library).它已经提供好些函数来帮助你诊断你的代码和跟踪内存泄漏. 而且最方便的地方是这些函数在Release版本中完全不起任何作用,这样就不会影响你的Release版本程序的运行效率.
    比如下面的例子里面,有一个明细的内存泄漏.当然如果只有这么几行代码的话,是很容易看出有内存泄漏的.但是想在成千上万行代码里面检查内存泄漏问题就不是那么容易了.
        char * pstr = new char[5];
        lstrcpy(pstr,"Memory leak");
    我们如果我们在Debug版本的Code里面对堆(Heap)进行了操作,包括malloc, free, calloc, realloc, new, 和 delete可以利用VC Debug运行时库中堆Debug函数来做堆的完整性和安全性检查. 比如上面的代码,lstrcpy的操作明显破坏了pstr的堆结构.使其溢出,并破坏了临近的数据.那我们可以在调用lstrcpy之后的代码里面加入_CrtCheckMemory函数._CrtCheckMemory函数发现前面的lstrcpy使得pstr的堆结构被破坏,会输出这样的报告:
    emory check error at 0x00372FA5 = 0x79, should be 0xFD.
    memory check error at 0x00372FA6 = 0x20, should be 0xFD.
    memory check error at 0x00372FA7 = 0x6C, should be 0xFD.
    memory check error at 0x00372FA8 = 0x65, should be 0xFD.
    DAMAGE: after Normal block (#41) at 0x00372FA0.
    Normal located at 0x00372FA0 is 5 bytes long.
    它告诉说 pstr的长度应该时5个Bytes,但是在5Bytes后面的几个Bytes也被非法改写了.提醒你产生了越界操作.
    _CrtCheckMemory的返回值只有TRUE和FALSE,那么你可以用_ASSERTE()来报告出错信息. 上面的语句可以换成 _ASSERTE(_CrtCheckMemory()); 这样Debug版本的程序在运行的时候就会弹出一个警告对话框,如图1,这样就不用在运行时候一直盯着Output窗口看了.这个时候按Retry,就可以进入源代码调试了.看看问题到底出在哪里

                        图1
    其他类似的函数还有_CrtDbgReport, _CrtDoForAllClientObjects, _CrtDumpMemoryLeaks,_CrtIsValidHeapPointer, _CrtIsMemoryBlock, _CrtIsValidPointer,_CrtMemCheckpoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince, _CrtMemDumpStatistics, _CrtSetAllocHook, _CrtSetBreakAlloc, _CrtSetDbgFlag,_CrtSetDumpClient, _CrtSetReportFile, _CrtSetReportHook, _CrtSetReportMode
    这些函数全部都可以用来在Debug版本中检查内存的使用情况.具体怎么使用这些函数就不在这里说明了,各位可以去查查MSDN.
    在这些函数中用处比较大的,或者说使用率会比较高的函数是,_CrtMemCheckpoint 设置一个内存检查点.这个函数会取得当前内存的运行状态.  _CrtMemDifference 检查两种内存状态的异同. _CrtMemDumpAllObjectsSince 从程序运行开始,或者从某个内存检查点开始Dump出堆中对象的信息. 还有就是_CrtDumpMemoryLeaks当发生内存溢出的时候Dump出堆中的内存信息. _CrtDumpMemoryLeaks一般都在有怀疑是内存泄漏的代码后面调用,比如下面的例子
    #include <windows.h>
    #include <crtdbg.h>
    void main()
    {
    char * pstr;
    pstr = new char[5];
    _CrtDumpMemoryLeaks();
    }
       输出:
        Detected memory leaks!  à提醒你,代码有内存泄漏.
    Dumping objects ->
    {44} normal block at 0x00372DB8, 5 bytes long.
         Data: <     > CD CD CD CD CD
    Object dump complete.
    如果你双击包含行文件名的输出行,指针将会跳到源文件中内存被分配地方的行.
    当无法确定那些代码产生了内存泄漏的时候,我们就需要进行内存状态比较. 在可疑的代码段的前后设置内存检查点,比较内存使用是否有可疑的变化.以确定内存是否有泄漏.为此要先定义三个_CrtMemState 对象来保存要比较的内存状态.两个是用来比较,一个用了保存前面两个之间的区别
    _CrtMemState Sh1,Sh2,Sh_Diff;
    char *pstr1 = new char[100];
    _CrtMemCheckPoint(&Sh1);  ->设置第一个内存检查点
    char  *pstr2 = new char[100];
      _CrtMemCheckPoint(&Sh2); ->设置第二个内存检查点
      _CrtMemDifference(&Sh_Diff, &Sh1, &Sh2);  ->检查变化
      _CrtMemDumpAllObjectsSince(&Sh_Diff);   ->Dump变化

    如果你的程序中使用了MFC类库,那么内存泄漏的检查方法就相当的简单了.因为Debug版本的MFC本身就提供一部分的内存泄漏检查. 大部分的new 和delete没有配对使用而产生的内存泄漏,MFC都会产生报告.这个主要是因为MFC重载了Debug版本的new 和delete操作符. 并且对前面提到的API函数重新进行了包装.在MFC类库中检查内存泄漏的Class就叫 CMemoryState,它重新包装了了_CrtMemState, _CrtMemCheckPoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince这些函数.并对于其他的函数提供了Afx开头的函数,供MFC程序使用 比如 AfxCheckMemory, AfxDumpMemoryLeaks 这些函数的基本用法同上面提到的差不多. CMemoryState和相关的函数的定义都在Afx.h这个头文件中. 有个简单的办法可以跟踪到这些函数的申明. 在VC中找到MFC程序代码中下面的代码, 一般都在X.cpp的开头部分
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    把光标移到DEBUG_NEW上面 按F12,就可以进入Afx.h中定义这些Class和函数的代码部分. VC中内存泄漏的常规检查办法主要是上面的两种.当然这两种方法只是针对于Debug版本的Heap的检查.如果Release版本中还有内存泄漏,那么检查起来就麻烦很多了.
    4 .总结:
        实际上Heap的内存泄漏问题是相当的好查的.VC的提供的检查工具也不太少,但是如果是栈出了什么问题,恐怕就麻烦很多了. 栈出问题,一般不会产生内存泄漏,但是你的代码的逻辑上很有可能会有影响.这个是最最痛苦的事情. 编程,就是小心,小心再小心而已.
    (本文未最后定稿,处于修改之中,文中有图限于专栏的限制,以去掉,但是不影响阅读)

                                            很土 最后完成时间 2003-3-15 中午
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2018-2-28 18:04
  • 签到天数: 40 天

    连续签到: 1 天

    [LV.5]测试团长

    3#
    发表于 2005-5-26 10:25:21 | 只看该作者
    Bounds checker好像可以检测内存泄漏。试试看吧。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    4#
     楼主| 发表于 2005-5-26 11:07:52 | 只看该作者
    谢谢你了,版主。只是我用的是.net的C#作的东东。控件有调用API的但是查过了没问题。看过你给的那篇文章倒是有点启发,谢谢了。再看看boundchecker吧.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    5#
     楼主| 发表于 2005-5-26 16:49:31 | 只看该作者
    问题已经找到,在循环中多重加载的地方加上CG.Collect();效果十分明显,说明一个问题:.net的自动回收做的不是很好。很多地方都要手动释放。呵呵。谢谢关注的人们
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    6#
    发表于 2005-10-8 16:37:31 | 只看该作者
    很受用!!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    7#
    发表于 2005-10-9 16:31:42 | 只看该作者
    编程一直没学好,学海无涯阿!谢啦!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    8#
    发表于 2006-3-28 15:27:39 | 只看该作者
    purify可以检测内存泄漏
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    9#
    发表于 2006-4-1 17:54:41 | 只看该作者
    谢谢你了!!!!!支持一下!!!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    10#
    发表于 2006-4-3 15:52:34 | 只看该作者

    我的问题

    sdlkfj
    各位电脑高手,能我提一意见吗?
    我这里电脑怎么刚进去的时候好卡,但过了一段时间后就好了,
    大概卡那么几分钟就好了,我不知道这是什么问题,能否给我一个解答。
    在此深表感谢。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    11#
    发表于 2006-4-25 10:13:04 | 只看该作者
    今天看了这个帖子,受益匪浅,谢谢了。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    12#
    发表于 2006-5-9 19:08:21 | 只看该作者

    没太看懂

    没太看懂,但有点启发 辛苦了
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    13#
    发表于 2006-8-27 14:28:23 | 只看该作者
    很受用啊
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    14#
    发表于 2007-5-17 13:29:22 | 只看该作者
    受教了,谢谢!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    15#
    发表于 2007-5-17 14:46:53 | 只看该作者
    听说FireFox也有严重的内存泄漏(几百个),不知道是不是真的???
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    16#
    发表于 2007-5-24 11:14:21 | 只看该作者
    至少知道了从哪入手解决内存泄露问题......
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    17#
    发表于 2007-5-25 11:07:20 | 只看该作者
    学习一下,学海无涯.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    18#
    发表于 2007-5-25 12:20:32 | 只看该作者
    好高深啊
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    19#
    发表于 2007-5-26 12:09:28 | 只看该作者
    高深
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    20#
    发表于 2007-8-17 10:52:37 | 只看该作者
    对.net只看 了一本书,没学深,只好路过
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-27 18:07 , Processed in 0.079046 second(s), 28 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

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