【问题标题】:How to find dispose and memory issues? C#如何找到处置和内存问题? C#
【发布时间】:2009-07-24 23:27:35
【问题描述】:

不久前我的应用使用了 150mb 的内存,现在是 286mb。它慢慢升起,所以我一定是忘记处理一些东西了。这对我来说不是什么大问题,因为我有 4gb,但我想把它发送给只有 1gb 内存的其他人。除了逐行查看代码,我如何才能找到需要处理的对象或通常是大对象?

【问题讨论】:

    标签: c# memory-leaks performance


    【解决方案1】:

    扩展 JP 和 Reed 的答案。

    我想澄清一点困惑。如果您看到内存显着增加,则该问题不太可能是调用 Dispose 的问题。 Dispose 通常用于释放句柄等非托管资源。这些不会占用太多内存,而是作为资源更宝贵。

    内存的增加通常与可从托管对象访问的大型对象或集合相关联,该托管对象通过堆栈对象或强 GC 句柄直接或间接作为根。这是您可能希望重点调查的领域。

    【讨论】:

    • 是的,这是一个很好的观点。我使用内存分析器来实现诸如“哦,那个集合不应该永远变得越来越大!”之类的事情。 :)
    • 另外,请仔细查看您订阅的所有活动。该事件包含对订阅者的引用,如果您从不取消订阅,则永远不会删除该引用。
    【解决方案2】:

    查看.NET Memory Profiler。有 15 天的试用期,值得支付许可费。

    通过以下方式轻松识别内存泄漏 收集和比较快照 .NET 内存快照包括数据 关于 .NET 实例分配 和当时的实时实例 快照已收集。他们提供了一个 很多有用的信息,并使它 易于识别潜在记忆 泄漏,尤其是当两个快照 进行比较。

    【讨论】:

      【解决方案3】:

      【讨论】:

        【解决方案4】:

        您还可以使用 WinDbg 和 SOS。这些具有免费且非常非常彻底的优势,如果有点难以习惯的话。

        这里有一个blog post 描述了这个过程。

        【讨论】:

        【解决方案5】:

        代码项目目前有一个指向专门用于查找未处置对象的应用的链接。

        http://www.codeproject.com/KB/dotnet/undisposed.aspx

        【讨论】:

          【解决方案6】:

          查看this link

          Stephen Toub 详细解释了执行此操作的各种技术, 以下是他文章中的一些简短亮点

          • 通过添加一个用于调试目的的终结器,您可以引入一种方法来找出何时 一个类没有正确处理,如果终结器从未被调用,你知道 处置没有被调用

          • 获取有关实例、threadId 等的其他信息以帮助缩小范围 哪个实例没有被调用,他创建了一个 FinalizationDebgger 类 您的一次性班级将持有哪个,而后者又会调用 Dispose 的 FinalizationDebugger 类实例,当它本身被释放时。如果未调用 Dispose 你的类实例然后当终结器运行时它将调用终结器 FinalizationDebgger 实例,您可以在其中断言或抛出异常以帮助调试 问题,

          • 将所有跟踪相关代码移动到一个基类中,您的一次性类将 然后继承自,这使代码更清晰。这种方法可能有效,也可能无效 因为你烧了一个基类,如果你已经从另一个基类继承了。

          • 在最后一个选项中,所有内容都被分解为您的实例的静态类 呼入。 FinalizationDebugger 变成了一个静态类,暴露了三个静态 方法:构造函数、处置和终结器。这个想法是你调用这些方法 从您班级中的适当位置(处置/最终确定/构造函数)。这是最低限度的 侵入您的代码,因为它通常只涉及添加三行代码。全部 这些方法中有一个用 ConditionalAttribute 标记,因此它们只会被调用 当你在调试模式下编译你的类时由你的类。

          Stephen 还解释了他的每种方法的优缺点。 这些解决方案提供了各种选项,您需要对每个选项进行评估,以确定哪一个最适合您的情况。必须阅读恕我直言

          希望这会有所帮助。

          【讨论】:

          • 需要更好地填写答案以获得投票。仅仅指向一个链接是不够的,因为如果链接失效,这不再是一个有用的答案。
          • 很公平,编辑答案以包含 MSDN 文章中所涵盖内容的简短摘要
          【解决方案7】:

          也可以试试ANTS Memory Profiler。有 14 天的全功能免费试用,我真的很喜欢这个 UI。

          披露:他们现在赞助 Herding Code,这就是我尝试的原因。但我对它印象深刻——我分析了一个应用程序 30 小时并从中获得了大量有用的信息。用户界面真的很有帮助 - 它指导您完成整个过程,而且看起来很糟糕。

          alt text http://www.red-gate.com/products/ants_memory_profiler/images/object_retention_graph.gif

          【讨论】:

            【解决方案8】:

            这里有几个技巧使用ANTS Memory Profiler 来帮助找到未处理的对象并修复泄漏。

            1. ANTS 内存分析器允许设置过滤器,仅显示 包含 Dispose() 方法的对象。打开这个,你会 给定一个尚未处理的活动对象列表。

            2. 虽然查找未处理的对象很有用,但更有用的是 知道为什么这些对象没有被处理。寻找这些在哪里 创建未处理的对象对找到 泄漏的原因。如果您能够更改泄漏对象的代码,则 有用的技巧是引入一个字段来保存堆栈跟踪,并且 在对象构造时填充此字段。那么因为 ANTS 内存分析器允许您检查对象的字段, 您可以简单地读取堆栈跟踪,就像创建泄漏对象时一样。这会给你一个强有力的线索来判断谁 泄漏对象的所有者应该是,以及他们应该如何对他们负责的对象调用 Dispose。

            【讨论】:

              猜你喜欢
              • 2021-04-01
              • 1970-01-01
              • 2010-11-05
              • 2013-12-16
              • 2010-12-31
              • 2021-07-15
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多