2

我正在尝试使用 dotMemory 进行简单测试。我希望以下测试会通过:

[Test]
public void MemoryStream_is_disposed()
{
    using (var stream = new MemoryStream()) { }
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
    dotMemory.Check(memory => memory.GetObjects(where => where.Type.Is<MemoryStream>()).ObjectsCount.Should().Be(0));
}

但事实并非如此!

在此处输入图像描述

为什么,我需要做什么才能通过考试?

这可能就是我的代码中有内存泄漏的原因。

4

1 回答 1

2

已处置有资格进行垃圾收集意味着两件不同的事情。特别是,您stream有资格进行垃圾回收不是因为它已被释放,而是因为您在调用时没有对该对象的未完成引用GC.Collect

但是,正如@alexeilevenkov 指出的那样,GC 的调试版本在标记阶段没有那么激进,当引用在函数范围内时保持引用处于活动状态(允许您检查流引用直到函数结束)。有资格进行垃圾收集意味着该对象可能会被垃圾收集。但是,由 GC 决定何时实际收集东西。

事实上,在发布模式下,即使引用该对象的变量仍在范围内,对象也有可能获得收集和收集的资格。如果创建了一个对象,将其分配给一个变量,并在范围顶部附近使用,但从未在该范围内再次使用,则该对象可能在变量超出范围之前被收集。

除了在对该对象的最后一个活动引用完成之后才能收集对象的规则之外,您不应该对何时发生收集做出任何假设。

为什么你认为你的代码中有内存泄漏?在托管代码中检测真正的内存泄漏很困难

于 2020-02-29T21:14:07.657 回答