请大家推荐一个快速检查表/最佳实践指南,以帮助我们避免可能导致.NET应用程序内存泄漏的简单(但细微)错误。
我发现在项目的测试阶段开始寻找内存泄漏的原因非常困难和痛苦。
如果有“经验法则”可以完全指导管理应用程序中的内存泄漏,我恳请您分享您的经验。
谢谢。
(我认为托管应用程序应该是“内存管理”的,即GC?为什么我们仍然在纯托管代码中发现泄漏?)
最佳答案
有多种形式的泄漏:
非托管泄漏(分配非托管代码的代码)
资源泄漏(分配和使用非托管资源的代码,如文件、套接字)
物体寿命延长
对gc和.NET内存管理工作方式的理解不正确
.NET运行时中的错误
前两个通常由两个不同的代码处理:
在对象上实现IDisposable并在Dispose方法中释放非托管内存/资源
实现终结器,以确保在GC发现对象符合收集条件时释放非托管资源。
然而,第三个不同。
假设您使用的是一个包含数千个对象的大列表,总内存大小相当大。如果您将对该列表的引用保留的时间超过了需要的时间,那么您将遇到类似内存泄漏的情况。另外,如果您不断地向这个列表中添加数据,使它周期性地随着更多的数据而增长,并且旧数据永远不会被重用,那么肯定会出现内存泄漏。
我经常看到的一个原因是将方法附加到事件处理程序,但在完成后忘记注销它们,慢慢地增加要执行的事件处理程序的大小和代码。
第四,对.NET内存管理工作方式的不正确理解可能意味着您在进程查看器中查看内存使用情况,并注意到您的应用程序的内存使用不断增加。如果您有大量的可用内存,GC可能不会经常运行,这会使您对当前的内存使用情况有错误的了解,而不是映射内存。
第五,这更难了,到目前为止,我在.NET中只看到一个资源管理错误,而在.NET 4.0中,Afaik计划修复它,它是将桌面屏幕复制到.NET图像中。
编辑:对于评论中的问题,如何避免将引用保留的时间超过必要的时间,那么唯一的方法就是这样做。
让我解释一下。
首先,如果您有一个长期运行的方法(例如,它可能是在磁盘上处理文件,或者下载某些东西,或者类似的东西),并且在方法的早期,在长期运行的部分之前,使用了对大数据结构的引用,然后在met的其余部分中不使用该数据结构。hod,然后是.NET,在发布版本中构建(而不是在调试器下运行),它足够聪明,可以知道这个引用,尽管它保存在一个从技术上讲在范围内的变量中,但可以进行垃圾收集。垃圾收集器在这方面真的很有侵略性。在调试生成和在调试程序下运行时,它将在方法的生命周期中保留引用,以防您希望在断点处停止时检查它。
但是,如果引用存储在声明方法的类中的字段引用中,那么它就不那么聪明了,因为不可能确定是否在以后重用它,或者至少非常难。如果这个数据结构变得不必要,您应该清除保存在它上面的引用,以便GC稍后可以提取它。
关于.net - 托管(.net)应用程序中最常见(通常被忽视)的内存泄漏原因是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/672810/