views:

64

answers:

1

Is there a way to get the "address" of an object? This is for demonstration purposes, I know this is a bad idea in general and if it works at all then as unsafe code. The project is tuned to allow unsafe code. However my tries were unsuccessful. The code I have so far is not compiling:

    unsafe static String AddressOf(Object o)
    {
        void* p = &o;
        return String.Format("{0}", new IntPtr(p));
    }

Error: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object')

Even if The memory address cannot be retrieven, then maybe a memory slot or something else showing the location of that object.

Background: my intention is to make some demo showing the differences between passing by value or by reference and dump the location of these objects.

ADDED 2010-06-27:

I finally abandonned the idea of doing it from within the .NET program itself. Seems not to lead to any good solution. Even if it had worked it would have cluttered the code so much that you can barely explain the result in simple ways and use it for some demo purpose. I would now like to do it with a good (meaning CLR aware) debugger in the way that is adviced in the answer below.

Debugging can be improved inside VS by activating an option in the configuration settings Enable Unmanaged Debugging, unfortunately not available in the free express edition of visual studio (the only version I have at home right now). Is there a way to make Enable Unmanaged Debugging work manually?

After struggling a bit I installed Debugging Tools for Windows which provided me the WinDbg. Great tool I used years ago for driver development. Now it's part of a huge package. I tried to follow the instructions to get the SOS.DLL way working without success. I cannot even find this DLL. Even this solution seems to require the Enable Unmanaged Debugging flag in the project...

+2  A: 

To make the demo meaningful, you need to pin the object first.

GCHandle handle = GCHandle.Alloc(o, GCHandleType.Pinned);
IntPtr address = handle.AddrOfPinnedObject();

I would demonstrate using SOS (part of the Debugging Tools for Windows package). You & your audience will actually gain some valuable skills that way, rather than just hand-waving about CLR implementation details.

Richard Berg
The hint with SOS looks great. The try with GCHandle ended at runtime with a `Object contains non-primitive or non-blittable data.`. Looks like a step in the right direction, just have to make it work somehow. If you know of to solve this, please go on :-). At least it is something I didn't investigate before.
jdehaan
Like the error says, you can't pin an object that references other objects. Put another way: pinning isn't recursive. Either switch back to grabbing a normal handle -- rolling the dice that the GC won't move your object while you're examining it -- or do **all** of your investigation under the debugger, with the managed threads frozen, rather than trying to print the addresses from .NET.
Richard Berg
This doesn't help. It shows the (temporary) address of the object in the GC heap. It will be the same whether you pass by value or by reference.
Hans Passant
@Richard, ok but the class just has an `int` member and a few methods that's it... I think I need some time to understand this and make it work before definively accepting, but I have the feeling it is the right direction. Thanks.
jdehaan
I am still a bit stuck. I believe it's due to the Express version I use. I have to experiment with a full version next week in the lunch break... I will also have a look at a free alternative maybe with the newest SharpDevelop.
jdehaan
The IDE you use to compile it makes no difference. Also, the "enable unmanaged debugging" option you mention in your edit is not even a compiler option -- it's an IDE feature. (google this: "mixed mode debugging") If you're having trouble using WinDBG, post a new question with the relevant steps.
Richard Berg