我的应用程序不久前使用的是150mb的内存,现在是286mb。它慢慢升起,所以我必须忘记丢弃一些东西。这对我来说不是一个问题,因为我有4gb,但我想把它发送给只有1gb内存的其他人。然后逐行浏览代码我怎样才能找到需要处理的对象或者只是一般大的对象呢?
答案 0 :(得分:5)
扩展JP和Reed的答案。
我想澄清一点混乱。如果您看到内存显着增加,则调用Dispose不会出现问题。 Dispose通常用于释放非托管资源,如句柄。这些不占用太多内存,而是作为资源更珍贵。
内存的增加通常与可以从直接或间接通过堆栈对象或强GC句柄间接生根的托管对象访问的大对象或集合相关联。这是您可能希望集中研究的领域。
答案 1 :(得分:2)
查看.NET Memory Profiler。有15天的试用期,非常值得许可费。
轻松识别内存泄漏 收集和比较的快照 .NET内存快照包括数据 关于.NET实例分配 当时的实时实例 收集了快照。他们提供了一个 很多有用的信息,并使它 容易识别潜在的记忆 泄漏,尤其是两个快照时 比较。
答案 2 :(得分:1)
答案 3 :(得分:1)
您还可以使用WinDbg和SOS。如果有点习惯,它们具有免费且非常彻底的优点。
这是描述该过程的blog post。
答案 4 :(得分:0)
代码项目目前有一个指向专门用于查找未处置对象的应用程序的链接。
答案 5 :(得分:0)
Stephen Toub竭尽全力解释这样做的各种技巧, 以下是他的文章中的一些简要介绍
通过添加终结器进行调试,您可以介绍一种查找时间的方法 一个类没有妥善处理,如果永远不会调用终结器,你就知道了 处置不被称为
要获取有关实例,threadIds等的其他信息,以帮助缩小范围 哪个实例没有调用它,他创建了一个FinalizationDebgger类 你的一次性课程会坚持哪个会转而称之为的 处理它本身时的FinalizationDebugger类实例。如果未调用Dispose 你的类实例然后当Finalizer运行时它会调用终结器 FinalizationDebgger实例,您可以在其中断言或抛出异常以帮助调试 问题,
将所有跟踪相关代码移动到您的一次性类所需的基类中 然后继承,这使代码更清洁。这种方法可能有效,也可能无效 因为你烧了一个基类,如果你已经从另一个基地继承了。
在最后一个选项中,所有内容都被分解为实例的静态类 打电话给。 FinalizationDebugger成为一个暴露三个静态的静态类 方法:构造函数,Dispose和Finalizer。这个想法是你称这些方法 从你班级的适当位置(dispose / finalize / constructor)。这是最低限度的 侵入您的代码,因为它通常只涉及三行代码。所有 这些方法用ConditionalAttribute标记,以便只调用它们 在DEBUG模式下编译类时,由您的类。
希望这有帮助。
答案 6 :(得分:0)
同时试用ANTS Memory Profiler。这是一个为期14天的全功能免费试用版,我非常喜欢用户界面。
披露:他们现在赞助Herding Code,这就是我尝试过的原因。但我对此印象非常深刻 - 我将应用程序描述了30个小时,并获得了大量有用的信息。用户界面非常有用 - 它会引导您完成整个过程,它看起来像是真的。
alt text http://www.red-gate.com/products/ants_memory_profiler/images/object_retention_graph.gif
答案 7 :(得分:0)
以下是使用ANTS Memory Profiler帮助查找未处置对象并修复泄漏的几个技巧。
ANTS内存分析器允许设置仅显示的过滤器 包含Dispose()方法的对象。打开它,你就会 给出一个尚未处置的活动对象列表。
虽然找到无关的对象很有用,但更有用的是 知道为什么没有处理这些物体。找到这些的地方 创建未公开的对象有很长的路要走 泄漏的原因。如果您能够更改泄漏对象的代码,a 有用的技巧是引入一个字段来保存堆栈跟踪,以及 在对象构造时填充此字段。然后因为 ANTS内存分析器允许您检查对象的字段, 您可以简单地读取堆栈跟踪,就像创建泄漏对象时一样。这将给你一个强有力的线索,谁是谁 泄漏对象的所有者应该是,以及如何在他们负责的对象上调用Dispose。