A major part of my daily work is to debug code either in Visual Studio or WinDbg.
Visual Studio has nice benefits when it comes to live debugging of managed code. As this is very convenient I often choose this tool for that specific scenario. But Visual Studio has some characteristics which make debugging managed code in some scenarios more complicated than debugging in WinDBG. What I’m talking about is the Watch window and the automatic display of variable and property content by hovering with the mouse over a property to show the value.
You think these two features provide major benefits to you when using the debugger? I agree with you!
But they also can make debugging non deterministic.
The reason is that Visual Studio executes the code inside the Getter of the property to show the value. Correct: it executes code outside the context of your debugging session! And in such a situation not even break points you would have set inside this Getter to see when it gets called is hit. So while inspecting variables in the watch window (e.g. using the “+” Sign) to see the inner properties or by adding a new property to the watch window you are actually executing the code of the Getter. And often the code inside the Getter modifies something – e.g. initializes some default values or even loads something from a database.
E.g. think about the following property of a class:
public class Info
{
private string _title = null;
public string Title
{
get
{
if (_title == null)
{
_title = SomeComplexCodeToRetrieveTheTitle();
}
return _title;
}
}
…
}
…
Info info = new Info();
Console.WriteLine(info.Title);
Lets assume you have set a breakpoint at the line of Console.WriteLine and also inside the SomeComplexCodeToRetrieveTheTitle method.
First the Console.WriteLine breakpoint will be hit. Before inspecting the value of the Title property the internal field _title would be null. But the value displayed to you in the debugger will show you the state AFTER executing the method in the SomeComplexCodeToRetrieveTheTitle method, even before you stepped over the line where it would be invoked if you wouldn’t have debugged the code.
In some scenarios that can make a huge difference. E.g. the breakpoint set inside the SomeComplexCodeToRetrieveTheTitle will not be hit again as the code will never be executed after you inspected the Title property value using the debugger.
So the act of monitoring modifies the monitored system.
Like with Schrödinger’s Cat you often cannot know the value of a property but by looking at it you might actually initialize its value and modify other things right at this time.
You can actually change the behavior of Visual Studio to turn off the automatic evaluation of properties – but the default is to perform the automatic evaluation. I usually think about changing this option only after I ran into a problem caused by this behavior.
Permalink
Terrific article! I'd always wondered about the under-hood aspects of this otherwise magic behaviour!
Permalink
Too true! Of course I think about changing the behavior and then decide against it in the end. It's a great tip to be aware of this behavior though I'd venture that the benefits, at least for the time being, still outweigh the risk.
Thanks for the reminder Stefan!
Permalink
U-R-G-H. Realizing this, I had a cold shiver running down my spine.
Now I wonder… could this somehow get worse when closures are involved? I have something to think of this evening. Thanks for the head up Stefan.