如何避免内存泄漏?

Jos*_*osh 14 c# memory-leaks

我可以使用哪些提示来避免应用程序中的内存泄漏?我有什么可以留意的陷阱或陷阱吗?

Otá*_*cio 21

在IDisposable对象上调用Dispose或使用该using子句.这应该照顾我能想到的大部分泄漏.

  • 不信任所有未受管理的代码,并且不包含在正确的IDisposable对象中. (8认同)

Jos*_*hua 12

请注意您删除了您使用的任何事件处理程序.在.NET中,它们是泄漏内存的最常见原因.

  • 我通常使用工具来查找内存泄漏 - deleaker. (2认同)

Kas*_*dum 7

正如ocdecio所提到的,请确保在Idisposable对象上调用Dispose,并记住在完成对象时删除事件处理程序.在构建使用非托管资源的类时,请务必实现Idisposable,以便用户知道有一些关键资源需要处理.

此外,即使垃圾收集为您做了相当多的工作,您也应该摆脱对您已完成的对象的引用.否则他们仍然会有一个根,他们将不会被GC.


Mar*_*ris 6

在这些情况下,不要低估工具的帮助性..NET内存分析器现在相当成熟和强大,如果你有一个复杂的应用程序,你认为应该释放的对象仍被其他东西作为参考,那么精确定位该引用的能力是非常宝贵的.

我刚刚完成了内存泄漏,其中一个WPF标签页托管了一个Windows窗体控件(因为这些标签保存了大量数据,您可以随意打开和关闭它们,只需等待GC清除内存关闭不是一个选项).我使用YourKit分析器在打开选项卡之前拍摄内存快照,打开选项卡,再次关闭它并拍摄另一个快照.在探查器内部,您可以在视觉上比较两个快照,并查看哪些对象在该过程中幸存,并将其引用关注回GC根目录.我没有其他剖析器的经验,但我知道如果YourKit无法满足您的需求,那里有一些.


编辑添加:

好吧,这不是避免内存泄漏,它正在修复它们.但是我会把它留在这里,因为我认为它是有用的信息,我认为没有足够的.NET开发人员知道这些工具.


hac*_*ken 5

我知道有些人会建议垃圾收集作为解决方案.但是有很多情况下垃圾收集不能提供您期望的结果.很容易最终保持一个杂散的引用,阻止整个内存链被释放.了解这是如何破坏DARPA Grand Challenge的入口.您可以认为这些不是内存泄漏,但如果程序希望释放内存,那么它仍然是一个问题.就像在C编程中一样,几个月后你就会明白如何确保不留下不需要的引用.


Fil*_*kun 5

内存泄漏是错误,所以一般来说 - 这个问题可以像"如何编写没有错误"一样回答?从长远来看 - 不可能没有bug,但你可以限制在发布的代码中使用它们的机会.

首先关注开发的代码质量并遵循其他人提到的指导原则.

  1. 简单性是金色的 - 代码越简单 - 错误或泄漏的可能性就越小
  2. 使用非托管资源时要小心--Windows句柄,数据库连接,GDI对象等.
  3. 用于IDisposables
  4. 为承载非托管资源的类实现IDisposable
  5. 确保删除对未使用对象的任何引用 - 包括棘手的事件处理程序

除此之外 - 实现测试以查看内存是否泄漏 - 单元,并发,压力和负载测试最有帮助.通过检查指标(perf计数器)查看内存是否泄漏.您还可以记录对象创建和破坏,并在测试结束时分析日志.