Search

Dereference error in QuickWatch window by zsozsop

Closed
as By Design Help for as By Design

1
Sign in to vote
0
Sign in to vote
Sign in
to vote
Type: Bug
ID: 180715
Opened: 8/14/2006 11:16:25 AM
Access Restriction: Public
0
Workaround(s)
0
User(s) can reproduce this bug
Using the Quick Watch window during debugging in Visual Studio 2005 the following expression gives an error:

Expression:
new Guid[] {Guid.Empty}

Value:
Cannot dereference expression. The pointer is not valid.

However, if the debuggee uses the Guid.Empty value in its code then the expression evaluated correctly.
Details (expand)
Product Language
English
Version
Visual Studio 2005 Team Suite
Operating System
Windows XP Professional
Operating System Language
English
Category
\Diagnostic Tools
Subcategory 1
\Debugger
Subcategory 2
\
Subcategory 3
 
Steps to Reproduce
To get the error:
1. Create a new console application.
2. Put a breakpoint anywhere in the code (in the empty Main method).
3. Start debugging.
4. When the breakpoint is hit, open the QuickWatch window and enter the following expression: new Guid[] {Guid.Empty}
5. Hit enter to get the expression evaluated.

---------------------------------------------------------
To get the expression evaluated successfully:
Same as above but in the Main method enter some Guid.Empty related code. E.g.:
Guid guid = Guid.Empty;
Start debugging as above and the expression will be evaluated successfully.
Actual Results
In the "Value" grid the following error message appears:
new Guid[] {Guid.Empty} Cannot dereference expression. The pointer is not valid. System.Guid[]
Expected Results
Get an array which contains only 1 element, the Guid.Empty value.
File Attachments
0 attachments
Sign in to post a comment.
Posted by Microsoft on 9/11/2006 at 11:15 AM
Zsozsop -

Thanks for reporting this. We're looking into it now.

Thanks,
Luke Hoban
Visual C# Program Manager
Posted by Microsoft on 9/12/2006 at 5:33 PM
Hi Zsozsop,
While we are investigating the issue, I have a workaround for you, use "new Guid[]{new Guid()}" in the watch or immediate window to do the samething.

Sreekar choudhary
C# Compiler Dev
Posted by Microsoft on 9/13/2006 at 11:13 AM
The debugging API in .Net are designed to be non-invasive, except func-evals. So inspecting a static field will not result in the static contructor for the class to be called. Therefore the field is uninitialized, this results in a error when getting its value.
If however you call the instance ctor for Guild (new Guid()) we func-eval it this will result in the static ctor to be called. Same is true if guid is used in the compiled code, the .Net runtime will call the ctor before accessing any static field or instance ctor.

Hope this helps,
Regards, Sreekar Choudhary
C# Compiler Dev
Posted by zsozsop on 9/14/2006 at 1:45 PM
Sreekar,

Thank you very much for the answer. The explanation is very reasonable, it just wasn't clear from the VS error message. But at least now I know that I shouldn't be surprised if I get the same result from my own managed debugger. :-)

However, something is still not clear. I've tried evaluating the following expression:
new string[] {string.Empty}
It got evaluated perfectly, no error message.

I checked in IL what can be the difference. Here are the definitions of the two fields:
.field static initonly public string Empty
.field static initonly public valuetype System.Guid Empty
They seem to be quite similar. And actually, both the Guid class and the String has a .cctor.
What is the difference between the two classes? Why is String handled differently? Is it already accessed somewhere in the background before the Main method is called (oh, I've removed the "string[] args" parameter from the Main method, thus it's not referenced from my code). Or does it matter that System.Guid is struct?

And I experimented even a little further with this and tried the following code:
class Program
{
public class Foo
{
    public static string Bar = "Bar";

    static Foo()
    {
     System.Diagnostics.Debug.WriteLine(".cctor");
     Console.WriteLine(".cctor");
    }
}

static void Main(string[] args)
{
}
}

Then I put a breakpoint on the Main method and run the code. The breakpoint was hit, and no message appeared in the Console or Output window. Then I evaluated the following expression using the QuickWatch window:
new string[] {Foo.Bar}
I expected to get the dereference error message but instead of it I got the correct array and the ".cctor" string appeared both in the Console and the Output window. This means that the static constructor was called to evaluate the expression.

My question is the same again. Why is my Foo class handled differently (its static constructor is called) than the Guid class?

I'm sorry for wasting your time but I'm really interested in this subject, because as I said I'm working on a managed debugger.

Thanks in advance.

Regards,
Zsolt Petrény
Posted by DavidSrbecky on 9/20/2006 at 3:04 PM
Disclaimer: I am not Microsoft employee

I believe that even before Main is entered some managed code is executed on the thread to setup the domain so there is good chance that Strings .cctor is called.

I think that generally CLR will call cctor whenever it wants. It depends on various aspects so you should not rely on the precise time - it can even change between release and debug builds.
For example:
1)In your current sample code: If you evaluate “Foo.Bar”, you get “Bar”.
2)Now add “object o = Foo.Bar;” to the main method: If you evaluate “Foo.Bar”, you get “null”.
3)Keep “object o = Foo.Bar;” and delete static constructor of Foo: The result will be “Bar” again :-)

Best regards,
David Srbecky
Posted by Microsoft on 9/18/2007 at 4:47 PM
This does not look specific to refence type since "Value" class below produced the same results as Class Bar

    public struct Value
    {
        public static string Bar = "Bar";

        static Value()
        {
            System.Diagnostics.Debug.WriteLine(".cctor");
            Console.WriteLine("Value.cctor");
        }
    }

A brief review of the ecma spec revealed this

If marked BeforeFieldInit then the type’s initializer method is executed at, or sometime before, first access to any static field defined for that type.
If not marked BeforeFieldInit then that type’s initializer method is executed at (i.e., is triggered by):
•    first access to any static field of that type, or
•    first invocation of any static method of that type or
•    first invocation of any constructor for that type

This explaing the behavior that DavidSrbecky noticed and reported in the comments.

I think the problem here might be specific to System.Guid and how the static field needs an explicit call to the type before it can function.