代码之家  ›  专栏  ›  技术社区  ›  Gluip

单元测试内存泄漏

  •  13
  • Gluip  · 技术社区  · 14 年前

    有没有一种方法可以断言我的代码没有从单元测试中泄漏内存?

    objectsThatShouldNotBeThereCount = MemAssertion.GetObjects<MyView>().Count;
    Assert.AreEqual(0, objectsThatShouldNotBeThereCount);
    

    我使用的是C#/Nunit,但我对任何有这方面哲学的人感兴趣。。。

    6 回复  |  直到 10 年前
        1
  •  7
  •   Alexander Hitesh Bavaliya    6 年前

    当托管类型使用非托管资源时,常常会引入内存泄漏。

    System.Threading.Timer 它以回调方法作为参数。由于计时器最终使用非托管资源,因此引入了一个新的GC根目录,该根目录只能通过调用计时器的根目录来释放 Dispose 方法。在这种情况下,您的类型也应该实现 IDisposable 否则,此对象永远无法被垃圾回收(泄漏)。

    您可以通过执行类似以下操作来为此场景编写单元测试:

    var instance = new MyType();
    
    // ...
    // Use your instance in all the ways that
    // may trigger creation of new GC roots
    // ...
    
    var weakRef = new WeakReference(instance);
    
    instance.Dispose();
    instance = null;
    
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
    Assert.IsFalse(weakRef.IsAlive);
    
        2
  •  5
  •   Cumbayah    14 年前

    事实上,如果存在资源泄漏,您可能会使用在其契约中包含显式Close/Dispose的对象(用于“使用…”构造)。在这种情况下,如果您可以控制类型,则可以从对象的Dispose实现中标记对对象的处置,以验证它们实际上已被释放,前提是您可以忍受生命周期管理泄漏到类型的接口中。

    如果执行后一种操作,就可以对契约式处理进行单元测试。在某些情况下,我使用了与IDisposable(扩展该接口)等效的特定于应用程序的方法来添加查询对象是否已被释放的选项。如果在类型上显式实现该接口,则不会对其接口造成太多污染。

    如果您无法控制所讨论的类型,那么您所需要的工具就是内存探查器(如其他地方所建议的)。(例如 dotTrace

        3
  •  1
  •   Ladislav Mrnka    14 年前

    你不需要单元测试你需要内存分析器。你可以从 CLR Profiler.

        4
  •  1
  •   stop-cran SimpleOne    8 年前
        5
  •  0
  •   Michael Lloyd Lee mlk    14 年前

    profiling API

    如何创建对象?直接或某种可以控制的方式。如果可控返回带有终结器的扩展版本,终结器注册它们已被释放。那么

    GC.Collect();
    GC.WaitForPendingFinalizers();
    Assert.IsTrue(HasAllOfTypeXBeenFinalized());
    
        6
  •  0
  •   Ergwun    14 年前

    比如说:

    long originalByteCount = GC.GetTotalMemory(true);
    SomeOperationThatMayLeakMemory();
    long finalByteCount = GC.GetTotalMemory(true);
    Assert.AreEqual(originalByteCount, finalByteCount);