zoukankan      html  css  js  c++  java
  • Net资源泄露

    from :http://blog.csdn.net/yuanhuiqiao/archive/2010/01/28/5264480.aspx

    内存泄露发生了怎么办?如何预防内存泄露的发生?我的经验是解决内存泄露的根本办法是编码时有预防意识。

      目录

    1.内存泄露

      1.1怎样才算是发生了内存泄露

      1.2判断工具(perfmon.msc)

        1.2.1perfmon.msc的使用

         1.2.2一些重要的性能计数器

       1.3其他检测工具

    2.如何在日常编程中预防内存泄露的发生

      2.1 Dispose()的使用

      2.2 using的使用

      2.3 事件的卸载

      2.4继承 IDisposable

        Net如何继承IDisposable接口,实现自己的Dispose()函数

    4.其他资源泄露

       GDI leak,handle leak。

     5.几个特例

     6.参考文献

      (1)发现并防止托管代码中出现内存泄漏 ;

     (2)

    正文

    1.内存泄露

       刚开始使用Net的读者(甚至做了一两年商业开发的同行)可能对Net的内存泄露不是很了解,甚至会说Net不存在内存泄露,他们会问“不是有GC机制吗?”恩,是有这么回事,它保证了通常应用时不用考虑头疼的资源释放问题,但这个机制不保证你开发的程序就不存在内存泄露(在此我们假设程序不存在逻辑错误等Bug,下同)。

      同时, 一方面,GC机制本身的缺陷造成的,它做Collect操作时是基于一定的算法,虽然这个算法随着Net版本的升级在逐步的优化,但还是不能保证及时迅速准确地把Garbage回收(一定程度上也没必要,特别是随着机器硬件性能的大幅提升,犯不着这么做,怎么着GC也是需要开支的),这就需要在编码过程中通知那些资源可以被释放,特别是大对象,否则可能造成“泄露”;另一方面,Net中托管资源和非托管资源的处理是有差异的,托管资源的处理是由GC自动执行的,而非托管资源 (占少部分,比如文件操作,网络连接等)必须显式地释放,否则就可能造成泄露。综合起来说的话,由于托管资源在Net中占大多数,通常不做显式的资源释放是可以的,不会造成明显的资源泄露,而非托管资源则不然,是发生问题的主战场,是最需要注意的地方。

       另外,照我看来,很多情况下,衰老测试关注的主要是有没有内存泄露的发生,而对其他泄露的重视次之。为什么这样做呢,我认为有两方面的原因,一是内存跟其他资源是正相关的,也就是说没有内存泄露的发生,其他泄露的发生概率也较小,其根本在于所有的资源最后会反应在内存上;另一个就是很多Net应用开发,用到的非托管资源,多提供Dispose方法的,而Dispose之后,不光内存及时释放,其他的也做了释放。因此,通常情况下我们主要关注的是内存的使用情况,而对自定义控件开发等情况则需要关注GDI,handle等其他资源的情况。

    1.1怎样才算是发生了内存泄露

      上面说了这么多,那么到底如何判断有没有内存泄露的发生呢?

      如果程序报“Out of memory”之类的错误,事实上也占据了很大部分的内存,应该说是典型的内存泄露,这种情况属于彻底的Bug,解决之道就是找到问题点,改正。但我的经验中,这种三下两下的就明显的泄露的情况较少,除非有人在很困的情况下编码,否则大多是隐性或渐进式地泄露,这种需经过较长时间的衰老测试才能发现,或者在特定条件下才出现,对这种情况要确定问题比较费劲,有一些工具(详见1.3)可以利用,但我总感觉效果一般,也可能是我不会使用吧,我想大型程序估计得无可奈何的用这个,详细的参见相关手册。

      需要强调的是,判断一个程序是不是出现了"memory leak",关键不是看它占用的内存有多大,而是放在一个足够长的时期(程序进入稳定运行状态后)内,看内存是不是还是一直往上涨,因此,刚开始的涨动或者前期的涨动不能做为泄露的充分证据。

      以上呢都是些感性的说法,具体的判断是否发生了内存泄露,可以通过一些性能计数器来测定。一般来讲,我测性能时,主要关注Process里 以下几个指标,如果这些量整体来看是持续上升的,基本可以判断是有泄露情况存在的。

    A.Handle Count

    B.Thread Count

    C.Private Bytes

    D.Virtual Bytes

    E.Working Set

    F.另外.NET CLR Memory下的Bytes in all heeps也是我比较关注的。

      通关观察,你如果发现这些参数是在一个区间内震荡的,应该是没有大的问题的,如果是一个持续上涨的状态,那你就得注意,很可能存在内存泄露。


    1.2判断工具(perfmon.msc)

      如何测定以上的计数器呢,我大多使用windows自带的perfmon.msc。在此稍微说说改工具的使用。

        1.2.1perfmon.msc的使用

          由于现在不能贴图,以后补齐吧。在Run中输入perfmon.msc,运行,其他的自己摸索,不难。

         1.2.2一些重要的性能计数器

          参考1,

         参考2

    1.3其他检测工具

      我用过的里面CLRProfiler 和dotTrace 还行(下载地址见链接)windeg也还行。不过坦白的说,准确定位比较费劲,最好还是按常规的该Dispose的加Dispose,也可以加GC.Collect()。

    2.如何在日常编程中预防内存泄露的发生

      2.1 Dispose()的使用

         如果使用的对象提供Dispose()方法,那么当你使用完毕或在必要的地方(比如Exception)调用该方法,特别是对非托管对象,一定要加以调用,以达到防止泄露的目的。另外很多时候程序提供对Dispose()的扩展,比如Form,在这个扩展的Dispose方法中你可以把大对象的引用什么的在退出前释放。

      2.2 using的使用

       using除了引用Dll的功用外,还可以限制对象的适用范围,当超出这个界限后对象自动释放,比如

      2.3 事件的卸载

      2.4 API的调用

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yuanhuiqiao/archive/2010/01/28/5264480.aspx

  • 相关阅读:
    古典问题rabbit
    输入两个正整数m和n,求其最大公约数和最小公倍数
    水仙花数
    输入一行字符,分别统计出其中英文字母,空格,数字和其他字符的个数。
    mybatis中的#和$的区别
    SpringMVC 中整合JSON、XML视图
    Gson简要使用笔记
    Spring Framework Artifacts
    Quartz的cron表达式
    清除svn文件目录的bat脚本
  • 原文地址:https://www.cnblogs.com/94cool/p/1695313.html
Copyright © 2011-2022 走看看