Garbage Collection should have removed object but WeakReference.IsAlive still returning true

后端 未结 5 954
时光说笑
时光说笑 2020-12-06 05:50

I have a test that I expected to pass but the behavior of the Garbage Collector is not as I presumed:

[Test]
public void WeakReferenceTest2()
{
    var obj =         


        
5条回答
  •  鱼传尺愫
    2020-12-06 06:06

    Hit the same issue as you - my test was passing everywhere, except for under NCrunch (could be any other instrumentation in your case). Hm. Debugging with SOS revealed additional roots held on a call stack of a test method. My guess is that they were a result of code instrumentation that disabled any compiler optimizations, including those that correctly compute object reachability.

    The cure here is quite simple - don't ever hold strong references from a method that does GC and tests for aliveness. This can be easily achieved with a trivial helper method. The change below made your test case pass with NCrunch, where it was originally failing.

    [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(Func getter)
    {
        return getter();
    }
    

提交回复
热议问题