【问题标题】:Memory leak testing and constant variables内存泄漏测试和常量变量
【发布时间】:2014-05-25 07:47:25
【问题描述】:

我正在进行测试以检测类的内存泄漏。我使用以下模式执行此操作:

  • 在测试设置中获取初始内存(使用GC.GetTotalMemory(true)
  • 执行操作,例如对象的实例化
  • Dispose 对象(通过useage 块)
  • 在测试拆卸时获取内存(再次使用相同的方法,所有对象都超出范围,因此应该被垃圾回收)
  • 理想情况下,断言初始内存和最终内存之​​间的差异 = 0

在我的测试中使用内存分析工具,我看到 const 字符串(和相关的)声明被计入测试的泄漏内存。我希望在进行初始内存测量时已经声明了这些值,这样它们就不会产生测试检测到的“泄漏”。但是,我不想运行操作代码两次,因为这会阻止我检测静态变量中的变量泄漏(比如没有清理不应该具有应用程序生命周期的单例模式对象)。

有没有办法做到这一点?我是否必须对每个测试用例的这些变量进行手动补偿(其缺点是必须积极维护,从长远来看这可能不会发生)?运行时有没有可以用于此目的的时刻?还是我必须接受我无法测试接近 0 字节的内存泄漏?

(对于那些感兴趣的人:我已经在使用 Wea​​kReferences 和 livelyness 检查来监控我在测试中实例化的对象是否被正确地垃圾收集,但这不会涵盖泄漏的私有状态)

【问题讨论】:

    标签: c# testing memory-leaks


    【解决方案1】:

    试图在托管内存中找到小的内存泄漏或多或少是徒劳的。相反,如果可能,请尝试更大的范围 - 分配对象 100 000 次,看看在清理方面是否有显着差异。

    不过,实际上,您可能想做一些完全不同的事情。对于托管泄漏,内存量通常不是非常可靠的检查。相反,您可能希望让您的应用程序在一个循环中反复运行,并使用例如CLRProfiler 查看对象的生命周期。如果有一些可疑的东西持续了几分钟甚至几个小时,那可能是泄漏。这为您提供了一个比仅检查内存大小更好的主意。

    当然,一般来说,你不应该真正关心。在它真正伤害你之前,寻找内存泄漏几乎没有什么好处。请注意,我说的是关于托管内存。您仅使用托管内存的任何地方都应引起重视 - 无论是本机代码、不安全指针还是任何其他形式的非托管句柄。请注意,这包括网络代码(套接字具有非托管内存)、文件操作(文件句柄)、一些同步原语(等待句柄)、图像数据(最值得注意的是 GDI+ 的 Bitmap 类,WPF 也充满了这些)等等.不过,一般来说,使用高级方法,您通常可以安全地忽略大多数问题,直到它们在现实条件下真正明显地显现出来。

    现在,说了这么多,你的方法无论如何都是可疑的。您必须强制 GC 运行(使用当前的实现,它只会根据内存压力进行收集,而不是因为您离开了范围 - 就 GCing 而言,堆栈是一个完全独立的问题)。强制进行完整 GC 的通常做法是这样的:

    1. GC.Collect();
    2. GC.WaitForPendingFinalizers();
    3. GC.Collect();

    然后整个过程需要您先预热所有内容,即。先做一个完整的循环测试。然后你执行一个完整的强制 GC,如上所述。然后你做(比如说)一千个循环的测试。在那之后,你再做一次完整的 GC。这应该让您更清楚地了解实际内存使用情况。

    静态字段内存泄漏只有在使用大量内存时才有意义(在这种情况下,您应该简单地问为什么要使用这么多内存,我能做些什么呢? ?),或者如果它们随着多次调用或随着时间的推移而增加(在这种情况下,这种方法仍然可以让您发现问题)。

    另外,你是什么意思,一个没有应用程序范围的单例对象?如果这就是您所需要的,那么您真的,真的不应该使用单例!您几乎无法控制何时创建或销毁单例,并且您无法在其被销毁后重新创建它。当然,现在大多数人可能会告诉你根本不要使用单例 - 原因之一是除非它们没有状态,否则它们或多或少会扼杀任何使用单元测试等实践的机会。

    【讨论】:

    • 好吧,它伤害了我们,因此寻找内存泄漏并创建测试以防止这些类中的后续泄漏被认为是有用的 :)
    • 我同意“没有单一对象”的想法,但这个项目已经存在多年,我们正在处理相当多的技术债务。而且我们目前更关注对象泄漏而不是实际的内存泄漏。我正在解决的具体问题之一是管理对象事件订阅到静态事件(不要让我开始:P)。
    • @Xilconic 是的,如果是这种情况,你最好实现自己的事件订阅机制:) 实现起来应该不会太难(你可以使用自己的 add 和 @987654323 @ implementations - 使用一些事件订阅管理器而不是默认值,您可以轻松摆脱这些泄漏:))。
    猜你喜欢
    • 2012-01-29
    • 1970-01-01
    • 2019-04-11
    • 2013-07-21
    • 2013-11-06
    • 1970-01-01
    • 2015-07-14
    • 1970-01-01
    • 2013-03-10
    相关资源
    最近更新 更多