tags:

views:

240

answers:

4

I am trying to trace managed object creation/disposing in a CLI/C++ prog:

::System::Diagnostics::Trace::WriteLine(String::Format(
    "Created {0} #{1:X8}", 
    this->GetType()->Name,
    ((UInt64)this).ToString()));

Which fails with

error C2440: 'type cast' : cannot convert from 'MyType ^const ' to 'unsigned __int64'

Is there a way to keep track of the unique object IDs this way? Thanks!

A: 

MyType ^const is a reference type. Hence it's in the managed memory space, and you can't get direct memory pointers to these types, as they can change at any time.

Is there a way to keep track of the unique object IDs this way? Thanks!

You could use MyType.GetHashCode();

cwap
+1  A: 

Check out the GCHandle type: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.aspx. Looks like it would do what you want, though it looks it would be a bit of a pain to use for your purposes...

brone
+1  A: 

Even if you could cast this to some integral value for display, it probably wouldn't be a useful unique identifier. This is because unlike C++, in C++/CLI the location of a (managed) object (and by extension the value of this) can potentially change during that object's lifetime. The (logically) same object could print two different strings at different points in the program.

Logan Capaldo
+3  A: 

First of all, why this doesn't work. Managed handle types ^ aren't pointers. They aren't just addresses. An instance of a managed type can and will be moved around in memory by GC, so addresses aren't stable; hence why it wouldn't let you do such a cast (as GC can execute at any moment, and you do not know when, any attempt to use such an address as a raw value is inherently a race condition).

Another thing that is often recommended, but doesn't actually work, is Object.GetHashCode(). For one thing, it returns an int, obviously not enough to be unique on x64. Furthermore, the documentation doesn't guarantee that values are unique, and they actually aren't in 2.0+.

The only working solution is to create a an instance of System.Runtime.InteropServices.GCHandle for your object, and then cast it to IntPtr - that is guaranteed to be both unique, and stable.

Pavel Minaev
This has the caveat that you have to remember to cleanup the GCHandle when you are done, no?
Logan Capaldo