GCHandle获取.net对象的地址(指针)

ali*_*hoo 5 .net c# pointers memory-management memory-address

我设法得到一个.net对象的地址

GCHandle objHandle = GCHandle.Alloc(obj,GCHandleType.WeakTrackResurrection);
int address = GCHandle.ToIntPtr(objHandle).ToInt32();  
Run Code Online (Sandbox Code Playgroud)

我可以通过回忆起这个对象

Object obj = GCHandle.FromIntPtr(IntPtr(address)).Target;
Run Code Online (Sandbox Code Playgroud)

好吧,目的是将地址存储在本机类中,并具有哪个本机对象与哪个.net对象相关联的信息.
AFAIK地址不会因为分配而改变,是真的还是有人有更好的想法来实现我的目的?

谢谢

the*_*oop 7

你需要固定GCHandle以阻止物体四处移动,因为GC会移动物体,因此未固定的指针可能会变得无效.固定对象会阻止它移动:

GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
Run Code Online (Sandbox Code Playgroud)

完成后你还必须释放手柄:

handle.Free();
Run Code Online (Sandbox Code Playgroud)

  • "无法固定具有非原始(非blittable)成员的实例." 微软说.这就是我使用WeakTrackResurrection的原因 (3认同)

Vin*_*ayC 5

正如Tim和thecoop所指出的那样,GCHandle.Alloc可能会阻止垃圾回收,但是实际对象地址可能会更改,因为GC可能会移动对象,除非您固定对象。此外,您的代码正在使用GCHandleType.WeakTrackResurrection,并且不会阻止垃圾回收。GCHandle.ToIntPtr将提供可以在非托管调用上往返的句柄地址。实际的对象地址将通过AddrOfPinnedObject方法给出。

话虽如此,IMO,您的代码可能用于将.NET对象与非托管对象相关联的目的。这是因为GCHandle.To/FromIntPtr会找回正确的GCHandle,并且您可以通过它访问.NET对象(前提是该对象未进行垃圾回收)。IMO,实际对象地址是否已更改应该无关紧要。