请任何人推荐一个快速清单/最佳实践指南,以帮助我们避免可能导致 .net 应用程序内存泄漏的简单(但微妙)错误
当我处于项目的测试阶段时,我发现开始寻找内存泄漏的原因非常困难且相当痛苦。
如果有“经验法则”可以完全指导托管应用程序中的内存泄漏,我恳求您分享您的经验。
Thanks.
(我认为托管应用程序应该是“内存管理”,即 GC?那么为什么我们仍然在纯托管代码中发现泄漏?)
泄漏有多种形式:
- 非托管泄漏(分配非托管代码的代码)
- 资源泄漏(分配和使用非托管资源的代码,如文件、套接字)
- 延长对象的生命周期
- 对 GC 和 .NET 内存管理工作原理的错误理解
- .NET 运行时中的错误
前两个通常由两段不同的代码处理:
- 在对象上实现 IDisposable 并在 Dispose 方法中处置非托管内存/资源
- 实现终结器,以确保当 GC 发现对象符合回收条件时释放非托管资源
然而,第三个则不同。
假设您正在使用一个包含数千个对象的大列表,总共占用了大量内存。如果您保留对此列表的引用的时间超过了需要的时间,就会出现看起来像内存泄漏的情况。此外,如果您不断向此列表添加内容,使其定期随着更多数据而增长,并且旧数据永远不会被重用,那么您肯定会出现内存泄漏。
我经常看到的这种情况的根源之一是将方法附加到事件处理程序,但在完成后忘记取消注册它们,从而导致事件处理程序的大小和要执行的代码慢慢膨胀。
第四,对 .NET 内存管理工作原理的错误理解可能意味着您在进程查看器中查看内存使用情况,并注意到您的应用程序的内存使用量不断增长。如果您有大量可用内存,GC 可能不会经常运行,从而给您提供错误的当前内存图usage内存,而不是映射内存。
第五,这更难,到目前为止,我只在 .NET 中看到了一个资源管理错误,据我所知,它已计划在 .NET 4.0 中修复,它是将桌面屏幕复制到 .NET 映像中。
Edit:针对评论中的问题,如何避免保留引用时间超过必要的时间,那么唯一的方法就是这样做。
让我解释。
首先,如果您有一个长时间运行的方法(例如,它可能正在处理磁盘上的文件,或下载某些内容,或类似的),并且您在该方法的早期(在长期运行之前)使用了对大数据结构的引用。运行部分,然后您不对该方法的其余部分使用该数据结构,然后 .NET 在发布版本中(并且不在调试器下运行)足够聪明,可以知道此引用,尽管它保存在从技术上讲,在范围内的变量有资格进行垃圾收集。垃圾收集器在这方面确实非常积极。在调试构建和在调试器下运行时,它将在方法的生命周期内保留引用,以防您想在断点处停止时检查它。
但是,如果引用存储在声明该方法的类中的字段引用中,则不太聪明,因为无法确定稍后是否会重用它,或者至少非常非常困难。如果这个数据结构变得不必要,你应该清除你持有的引用,以便 GC 稍后会拾取它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)