GCHandle to get the address (pointer) of a .net object

I managed to get the address of the .net object

GCHandle objHandle = GCHandle.Alloc(obj,GCHandleType.WeakTrackResurrection); int address = GCHandle.ToIntPtr(objHandle).ToInt32(); 

and I can remember the object

 Object obj = GCHandle.FromIntPtr(IntPtr(address)).Target; 

Well, the goal is to store the address in the native class and get information about which native object is output to some .net object.
AFAIK address does not change due to allocation, is this true or does anyone have a better idea to serve my purpose?

thanks

+3
memory-management pointers c # memory-address
source share
4 answers

As Tim and thecoop noted, GCHandle.Alloc can prevent garbage collection, but the actual address of the object can change, as the GC can move the object around if you don’t snap the object. In addition, your code uses GCHandleType.WeakTrackResurrection , and this will not prevent garbage collection. GCHandle.ToIntPtr will GCHandle.ToIntPtr handle address that can be disabled on an uncontrolled call. The actual address of the object will be specified by the AddrOfPinnedObject method.

All said, IMO, your code can serve the purpose of binding a .NET object to an unmanaged object. This is due to the fact that GCHandle.To/FromIntPtr will return the correct GCHandle to you, and you will be able to reach your .NET object through it (if garbage is not collected). IMO, this should be inconsequential if the actual address of the object has changed or not.

+3
source share

You will need to bind the GCHandle to stop the object from moving, as the GC moves the objects around, so an unbound pointer may become invalid. Binding an object stops its movement:

 GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned); IntPtr ptr = handle.AddrOfPinnedObject(); 

You will also have to free the handle when you are done:

 handle.Free(); 
+5
source share

What you receive is not really an address.

As you noticed, it works as the address most often, and you can remember the object using GCHandle.FromIntPtr. However, an interesting problem is that you are using GCHandleType.WeakTrackResurrection .

If your object with low reference information is collected (maybe it can, because it weakly refers to GCHandle), you still have IntPtr, and you can pass it to GCHandle.FromIntPtr () . If you do, you will return to zero considering that IntPtr has not been redesigned.

(If for some reason IntPtr has been redesigned by CLR, then you have problems. I'm not sure if this could happen.)

You are better off using either GCHandleType.Normal or GCHandleType.Pinned (if you need to take the address of the object in unmanaged code) if you want a strong reference to the object.

(To use GCHandleType.Pinned, your object must be, for example, primitive or have the [StructLayout] attribute or be an array of such objects.)

+2
source share

AFAIK address does not change due to allocation, this is true

The address of the managed entity changes. The garbage collector can move objects in memory. When the garbage collector runs, it collects unused objects and then arranges the remaining objects to minimize the total size of the managed heap.

Does anyone have a better idea that I should do my job?

I'm not sure if you will find a good way to hold a pointer to a managed object for long periods of time. You can link objects in memory and get their address in this way, but in C # you can link objects only within the framework of one method.

This will help if you explain in more detail what you are going to do with the pointer as soon as you do.

+1
source share

All Articles