This is a migrated thread and some comments may be shown as answers.

WeakReference with Enabled profiler problem

6 Answers 144 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Alexander
Top achievements
Rank 1
Alexander asked on 26 Sep 2013, 10:54 AM
Hello Telerik,

I've found a problem with WeakReference and JustMock profiler. Here is a simple test which fails if profiler is enabled and pass if profiler is disabled:

[TestMethod]
        public void WeakRefTest()
        {
            var obj = new object();
            var weakRef = new WeakReference(obj);
            obj = null;
            GC.Collect();

            Assert.IsNull(weakRef.Target);
        }

I'm using latest development build of JustMock. Is it expected behavior or a bug in profiler?

Thank you,
Alex

6 Answers, 1 is accepted

Sort by
0
Stefan
Telerik team
answered on 26 Sep 2013, 12:24 PM
Hi Alexander,

To make your test work, do any of the following:
  • place the [DisableAutomaticRepositoryReset] attribute on your test method, or
  • move it to a test assembly that doesn't reference JustMock, or
  • run the test only in Release, or
  • run the test only in x64.

It is not a bug in JustMock, but rather in the way GC handles references on the stack.

Try the following: wrap the body of the test in a try/finally block (leave the finally block empty), build in Debug, disable the JustMock profiler and run the test again. The test will fail. All you did was wrap the test in a no-op try/finally, yet the test fails! Now, build the test project in Release and run it again - the test will succeed!

What happens is that even though you have "obj = null" in your code, the JIT artificially extends the lifetime of the object assigned to it to go to the end of the method (end of the variable's scope). This effect is due to a combination of factors: the JIT sees that the assembly is built with Debug on, so it extends lifetimes for easier debugging; the GC sees the lifetime extensions and decides that this object should not yet be collected.

For an additional mind-twist, remove the "obj = null" line and run the test in Release - the test will still succeed! The JIT doesn't actually care whether you nullify your local variables like that or not - it's smart enough to deduce that you never use the obj variable after the point of calling "GC.Collect()" so it can tell the GC that that variable is no longer a root.

By the way, you won't observe this behavior if you run in x64. That's because the x64 JIT is totally different from the x86 JIT.

In short, you cannot rely on the behavior of the GC with respect to local variables because it is an implementation detail and often behaves unintuitively. Here's an answer to this question given by an expert. Here's another one.

For further information, read the documentation of DisableAutomaticRepositoryResetAttribute.

Regards,
Stefan
Telerik
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
Alexander
Top achievements
Rank 1
answered on 26 Sep 2013, 12:34 PM
Thank you, Stefan

Especially for detailed answer. It is still not clear for me why it works without profiler and not working with it. But anyway, now I have more than one solution for the problem.

Have a nice day,
Thank again,
Alex
0
Stefan
Telerik team
answered on 26 Sep 2013, 12:37 PM
Hi Alexander,

The profiler makes the test fail, because it wraps the bodies of all [TestMethod] methods in a try/finally block (for internal bookkeeping). This change doesn't affect the correctness of your code, but changes the way the GC behaves in subtle ways.

Regards,
Stefan
Telerik
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
Alexander
Top achievements
Rank 1
answered on 26 Sep 2013, 12:40 PM
Now its clear for me,

Thank you again!
0
Alexander
Top achievements
Rank 1
answered on 26 Sep 2013, 02:15 PM
Hm, cannot find anything about DisableAutomaticRepositoryReset attribute.
Where can I find it?

Unfortunately, Release and x64 seems to be not an option for me.
Most strange thing is the same test was working several weeks ago.

Thanks,
Alex
0
Stefan
Telerik team
answered on 26 Sep 2013, 02:35 PM
Hello Alexander,

I'm sorry for the mix-up. The attribute and its accompanying documentation will be made available in the internal build due today or tomorrow.

This behavior is pretty recent - implemented first in JustMock Q2 SP2 (2013.2.724).

Regards,
Stefan
Telerik
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
Tags
General Discussions
Asked by
Alexander
Top achievements
Rank 1
Answers by
Stefan
Telerik team
Alexander
Top achievements
Rank 1
Share this question
or