我正在进行测试以检测类的内存泄漏。我使用以下模式执行此操作:
GC.GetTotalMemory(true)
)useage
阻止)在我的测试中使用内存分析工具,我看到const字符串(和相关的)声明被计入泄漏的内存以进行测试。我希望在进行初始内存测量时已经声明了这些值,这样它们就不会产生测试检测到的“泄漏”。但是,我不想两次运行动作代码,因为这会阻止我检测静态变量中的变量泄漏(比如没有清理不应该有应用程序生命周期的单例模式对象)。
有办法做到这一点吗?我是否必须对每个测试用例的这些变量进行手动补偿(其缺点是必须积极维护,从长远来看可能不会发生)?在运行时有一个我可以用于此目的的时刻吗?或者我是否必须接受我无法测试0字节附近的内存泄漏?
(对于那些感兴趣的人:我已经在使用WeakReferences和生动性检查来监视我在测试中实例化的对象是否被正确地垃圾收集,但这不会涵盖泄漏的私有状态)
答案 0 :(得分:2)
尝试在托管内存中发现小内存泄漏或多或少是徒劳的。相反,如果可能的话,尝试更大的范围 - 分配对象100 000次,并查看清理是否存在显着差异。
在实践中,你可能想要做一些完全不同的事情。对于托管泄漏,内存量通常不是非常可靠的检查。相反,您可能希望让您的应用程序在一个周期内反复运行,并使用例如CLRProfiler查看对象的生存期。如果有可疑的东西挂了几分钟甚至几个小时,那可能就是泄漏。这比仅仅检查内存大小提供了更好的想法。
当然,一般来说,你真的不应该关心。在实际伤害你之前,寻找内存泄漏的好处很少。请注意我正在谈论仅关于托管内存。任何你不使用托管内存的地方都应该受到重视 - 无论是本机代码,不安全指针还是任何其他形式的非托管句柄。请注意,这包括网络代码(套接字具有非托管内存),文件操作(文件句柄),一些同步原语(等待句柄),图像数据(最值得注意的是GDI +的Bitmap
类,WPF也充满了这些)和更多。但是,通常情况下,使用高级方法,您通常可以安全地忽略大多数问题,直到它们在实际情况下明显显现出来。
现在,所有这一切,无论如何你的方法都是可疑的。你必须强制GC运行(使用当前的实现,它只会根据内存压力收集,而不是因为你离开了范围 - 就GCing而言,堆栈是一个非常独立的问题)。强制完整GC的通常做法是这样的:
然后整个过程需要你先温暖一切,即。首先完成一个完整的测试循环。然后,如上所述,您执行完全强制GC。然后你做(比方说)一千个测试周期。然后,你再做一次完整的GC。这应该可以让您更清楚地了解实际内存使用情况。
静态字段内存泄漏只有在他们要么处理大量内存时才会感兴趣(在这种情况下,你应该简单地问为什么这会使用如此多的内存,我该怎么办呢? ?),或者如果它们在多次调用或长时间内增加(在这种情况下,此方法仍然可以让您发现问题)。
另外,你的意思是什么,单个对象没有应用程序的范围?如果这就是你需要的,你真的,真的不应该使用单身人士!您几乎无法控制单例创建或销毁的时间,并且在被销毁后无法重新创建。当然,大多数人可能会告诉你现在根本不使用单身人士 - 其中一个原因是,除非他们没有国家,否则他们或多或少会杀死任何使用单元测试等做法的机会。