gpt4 book ai didi

c# - 垃圾回收应该已经删除了对象,但 WeakReference.IsAlive 仍然返回 true

转载 作者:可可西里 更新时间:2023-11-01 08:17:41 25 4
gpt4 key购买 nike

我有一个我希望通过的测试,但是垃圾收集器的行为并不像我想象的那样:

[Test]
public void WeakReferenceTest2()
{
var obj = new object();
var wRef = new WeakReference(obj);

wRef.IsAlive.Should().BeTrue(); //passes

GC.Collect();

wRef.IsAlive.Should().BeTrue(); //passes

obj = null;

GC.Collect();

wRef.IsAlive.Should().BeFalse(); //fails
}

在这个例子中,obj 对象应该被 GC,因此我希望 WeakReference.IsAlive 属性返回 false

似乎是因为 obj 变量声明在与 GC.Collect 相同的范围内,所以它没有被收集。如果我将 obj 声明和初始化移到测试通过的方法之外。

是否有人对此行为有任何技术引用文档或解释?

最佳答案

遇到了与您相同的问题 - 我的测试在所有地方都通过了,除了在 NCrunch 下(在您的情况下可能是任何其他仪器)。嗯。使用 SOS 进行调试揭示了在测试方法的调用堆栈中保留的其他根。我的猜测是它们是代码检测的结果,该代码检测禁用了所有编译器优化,包括那些正确计算对象可达性的优化。

这里的解决方法非常简单——永远不要持有来自执行 GC 和测试 active 的方法的强引用。这可以通过简单的辅助方法轻松实现。下面的更改使您的测试用例通过了 NCrunch,而它最初是失败的。

[TestMethod]
public void WeakReferenceTest2()
{
var wRef2 = CallInItsOwnScope(() =>
{
var obj = new object();
var wRef = new WeakReference(obj);

wRef.IsAlive.Should().BeTrue(); //passes

GC.Collect();

wRef.IsAlive.Should().BeTrue(); //passes
return wRef;
});

GC.Collect();

wRef2.IsAlive.Should().BeFalse(); //used to fail, now passes
}

private T CallInItsOwnScope<T>(Func<T> getter)
{
return getter();
}

关于c# - 垃圾回收应该已经删除了对象,但 WeakReference.IsAlive 仍然返回 true,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15205891/

25 4 0