views:

93

answers:

7

In C++ it is fairly simple to display the actual value of a pointer to an object. For example:

// hope this makes sense: (please edit if not)
void* p = New CSomething();
cout << p;

Is there a way to do something like this in .NET?

The value of doing this would/could only be educational, e.g. for purposes of demonstration as in displaying a value for students to see rather than just comparing for reference equality or null (nothing) to prove shallow copies, immutability etc.

A: 

I understand that if you provide the compiler the /unsafe option, you will be allowed to write 'unsafe' code, and with it have access to pointers.

I haven't tested this but found it in this artice

Edit:

Seems the main thing to remember is that you would have to mark any code using unsafe code with the unsafe keyword:

unsafe public static void Main()
davbryn
Unsafe code doesn't let you have pointers to managed types. See the [fixed](http://msdn.microsoft.com/en-us/library/f58wzh21%28v=VS.71%29.aspx) documentation.
Matthew Flaschen
+2  A: 

RuntimeHelpers.GetHashCode will give you an identity-based hash code. In practice, this is probably based on address. As explained:

"RuntimeHelpers.GetHashCode is useful in scenarios where you care about object identity. Two strings with identical contents will return different values for RuntimeHelpers.GetHashCode, because they are different string objects, although their contents are the same."

Interning of string literals is the main possible exception. This is actually the same in C++.

Matthew Flaschen
I'm not sure why you got downvoted. Sure your answer is different, but it is good food for thought. It's true that Object.GetHashCode() (which RuntimeHelpers is using) is based on the object's location in memory, as that's the only distinctive aspect of the object available at this level. I will often call Object.GetHashCode() during debugging just to verify two references do or don't point to the same object.
Matt Greer
A: 

In .Net you don't work with pointers at all. So you would create reference objects, of which you can always see the value.

When comparing reference objects, the references are compared, not the actual values! (Except for comparing strings, where the '==' is overloaded).

Maybe an .Net example of what you want to demonstrate would elaborate things...

Jo-wen
A: 
unsafe 
{
    object o = new Object(); 
    int *ptr = &o; //Get address

    Console.WriteLine((int)ptr); //Write address
}

You need to compile this with the /unsafe switch

Jesper Palm
Matthew Flaschen
Tim Robinson
Matthew Flaschen
My bad. Only been using this for Bitmap objects converted to byte arrays.
Jesper Palm
You can take an interior pointer to a field within an object. Or as @Jesper says, a pointer to the start of a string or an array.
Tim Robinson
+4  A: 

If this is for education purposes, I suggest you use a debugger instead. If you load SOS.dll (which is part of the .NET framework) into WinDbg or even Visual Studio, you can examine the actual objects in memory.

E.g. to list the heap use the !dumpheap -stat command. The !do command dumps a mananaged object on the specified memory address and so forth. SOS has numerous commands that will let you examine internal .NET structures, so it is a really useful tool for learning more about the runtime.

By using the debugger for this, you're not restricted to looking at demo applications. You can peek into the details of real applications. Also, you'll pick up some really useful debugging skills.

There are several excellent introductions to debugging using WinDbg + SOS. Check Tess' blog for lots of tutorials.

Brian Rasmussen
+4  A: 

You can use GCHandle to get the address of a pinned object. The GC can move objects around so the only sensible address to get is one of a pinned object.

GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
Console.WriteLine(handle.AddrOfPinnedObject().ToInt32());
handle.Free();

Remember though that GCHandle will only pin objects that are primitive or blittable types. Some objects are blittable (and you can set it up for demo purposes so it works) but any reference type will not be blittable.

You'll need to add an explicit blittable description using [StructLayout(LayoutKind.Sequential)] or use the debugger to directly inspect addresses of object that do not meet these criteria.

Ron Warholic
A: 

You can retrieve the address of an object in .NET, such as with unsafe code, but the address you get back will only be temporary -- it'll be a snapshot as of the point where you take the address.

The next time a garbage collection happens, the address of your object is likely to change:

  • If the object is no longer referenced from anywhere, it will be collected, and some other object will occupy that address
  • If the object is still being referenced, it will probably be promoted to a higher generation (and therefore moved to a different GC heap). Alternatively, if it's already in generation 2, it will probably be moved in memory as the heap is compacted.

The existence of the garbage collector is the reason why the int* pointer in @Jesper's exists in the scope of a { } block. The pointer is fixed only within that block; once execution leaves the block, the object is entitled to be collected and/or moved.

Tim Robinson