当前位置:  开发笔记 > 编程语言 > 正文

哪些策略和工具对于在.NET中查找内存泄漏有用?

如何解决《哪些策略和工具对于在.NET中查找内存泄漏有用?》经验,为你挑选了7个好方法。

我写了C++ 10年.我遇到了内存问题,但可以通过合理的努力来修复它们.

在过去的几年里,我一直在写C#.我发现我仍然遇到很多内存问题.由于不确定性,它们很难诊断和修复,而且因为C#的理念是你绝对不必担心这些事情.

我发现的一个特殊问题是我必须在代码中明确地处理和清理所有内容.如果我不这样做,那么内存分析器并没有真正帮助,因为有太多的混乱,你无法在他们试图向你展示的所有数据中发现泄漏.我想知道我是否有错误的想法,或者我所拥有的工具是不是最好的.

什么样的策略和工具对于解决.NET中的内存泄漏很有用?



1> GEOCHET..:

当我怀疑内存泄漏时,我使用Scitech的MemProfiler.

到目前为止,我发现它非常可靠和强大.它至少有一次拯救了我的培根.

GC在.NET IMO中工作得很好,但就像任何其他语言或平台一样,如果编写错误的代码,就会发生不好的事情.


是的,我和这个人一起去了,它帮助我找到了一些棘手的漏洞.我发现最大的泄漏是由他们通过互操作访问的非托管代码中的第三方库引起的.令我印象深刻的是,此工具检测到非托管代码以及托管代码中的泄漏.

2> Jay Bazuzi..:

只是为了忘记处理问题,请尝试本博文中描述的解决方案.这就是本质:

    public void Dispose ()
    {
        // Dispose logic here ...

        // It's a bad error if someone forgets to call Dispose,
        // so in Debug builds, we put a finalizer in to detect
        // the error. If Dispose is called, we suppress the
        // finalizer.
#if DEBUG
        GC.SuppressFinalize(this);
#endif
    }

#if DEBUG
    ~TimedLock()
    {
        // If this finalizer runs, someone somewhere failed to
        // call Dispose, which means we've failed to leave
        // a monitor!
        System.Diagnostics.Debug.Fail("Undisposed lock");
    }
#endif



3> Mark..:

我们在项目中使用了Red Gate软件的Ants Profiler Pro.它适用于所有基于.NET语言的应用程序.

我们发现.NET垃圾收集器在清理内存中对象时非常"安全"(应该是这样).它会保留对象只是因为我们可能会在将来某个时候使用它.这意味着我们需要更加小心我们在内存中膨胀的对象数量.最后,我们将所有数据对象转换为"按需膨胀"(就在请求字段之前),以减少内存开销并提高性能.

编辑:这是对"按需膨胀"的意思的进一步解释.在我们的数据库对象模型中,我们使用父对象的Properties来公开子对象.例如,如果我们有一些记录以一对一的方式引用其他"详细信息"或"查找"记录,我们将按如下方式构造它:

class ParentObject
   Private mRelatedObject as New CRelatedObject
   public Readonly property RelatedObject() as CRelatedObject
      get
         mRelatedObject.getWithID(RelatedObjectID)
         return mRelatedObject
      end get
   end property
End class

我们发现当内存中有大量记录时,上面的系统会产生一些真正的内存和性能问题.所以我们切换到一个系统,在这个系统中,对象只有在被请求时才会被充气,并且只在必要时才进行数据库调用:

class ParentObject
   Private mRelatedObject as CRelatedObject
   Public ReadOnly Property RelatedObject() as CRelatedObject
      Get
         If mRelatedObject is Nothing
            mRelatedObject = New CRelatedObject
         End If
         If mRelatedObject.isEmptyObject
            mRelatedObject.getWithID(RelatedObjectID)
         End If
         return mRelatedObject
      end get
   end Property
end class

事实证明这样做更有效率,因为对象在需要之前一直保持内存不足(访问Get方法).它在限制数据库命中和内存空间大量增加方面提供了非常大的性能提升.



4> 小智..:

除非您的应用程序是微不足道的,否则在编写托管代码时仍需要担心内存.我将建议两件事:首先,通过C#读取CLR,因为它将帮助您理解.NET中的内存管理.其次,学习使用像CLRProfiler(微软)这样的工具.这可以让您了解导致内存泄漏的原因(例如,您可以查看大对象堆碎片)


读取
因为它将帮助您理解.NET中的内存管理.其次,学习使用像

5> Timothy Lee ..:

您使用的是非托管代码吗?根据微软的说法,如果你没有使用非托管代码,传统意义上的内存泄漏是不可能的.

但是,应用程序使用的内存可能无法释放,因此应用程序的内存分配可能会在应用程序的整个生命周期中增长.

从如何识别Microsoft.com上的公共语言运行库中的内存泄漏

当您将非托管代码用作应用程序的一部分时,.NET Framework应用程序中可能会发生内存泄漏.此非托管代码可能会泄漏内存,.NET Framework运行时无法解决该问题.

此外,项目可能只会出现内存泄漏.如果声明了许多大对象(例如DataTable对象),然后将其添加到集合(例如DataSet),则会发生这种情况.这些对象拥有的资源可能永远不会被释放,并且资源在整个程序运行时都处于活动状态.这似乎是一个泄漏,但实际上它只是在程序中分配内存的方式的一个症状.

要处理此类问题,您可以实现IDisposable.如果你想看一些处理内存管理的策略,我会建议搜索IDisposable,XNA,内存管理,因为游戏开发者需要有更多可预测的垃圾收集,所以必须强制GC做它的事情.

一个常见错误是不删除订阅对象的事件处理程序.事件处理程序订阅将阻止对象被回收.另外,请查看using语句,该语句允许您为资源的生命周期创建有限的范围.


请参阅http://blogs.msdn.com/tess/archive/2006/01/23/net-memory-leak-case-study-the-event-handlers-that-made-the-memory-baloon.aspx.内存泄漏是否"传统"并不重要,它仍然是一个漏洞.
@Timothy Lee Russel:如果一个无限的(1)内存量在变得无用之后可以保持同时分配(root)(2),系统中没有任何东西可以及时取消根目录所需的信息和动力,那就是内存泄漏.即使有一天内存可能会被释放,如果在发生这种情况之前有足够的无用东西可能会积累以阻塞系统,那就是泄漏.(1)大于O(N),N是有用的分配数量; (2)如果删除对它的引用不会影响程序功能,则Stuff是无用的.
我明白你的观点 - 但是程序的低效分配和内存重用与内存泄漏不同.
@Timothy Lee Russel:正常的"内存泄漏"模式发生在一个实体*代表另一个实体*持有内存时,期望在不再需要它时被告知,但后者在不告诉第一个实体的情况下放弃实体.持有内存的实体并不真的需要它,但是没有办法确定它.

6> twk..:

这个博客有一些非常精彩的演练,使用windbg和其他工具来追踪所有类型的内存泄漏.优秀的阅读,以发展你的技能.



7> billybob..:

我刚刚修复了Windows服务中的内存泄漏问题.

首先,我尝试了MemProfiler.我发现它真的很难使用,而且根本不是用户友好的.

然后,我使用了更容易使用的JustTrace,并为您提供有关未正确放置的对象的更多详细信息.

它让我很容易解决内存泄漏问题.

推荐阅读
郑谊099_448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有