我设法通过

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

我可以通过

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

好吧,目的是将地址存储在本机类中,并提供一个对哪个本机对象的信息。
Afaik地址不会因为分配而改变,是真的还是有人有更好的主意来服务我的目的?

谢谢

有帮助吗?

解决方案

正如Tim和Thecoop所指出的那样,Gchandle.Alloc可能会防止垃圾收集,但是实际的对象地址可能会随着GC的移动而改变,除非您固定对象。此外,您的代码正在使用 GCHandleType.WeakTrackResurrection 而且这不会阻止垃圾收集。 GCHandle.ToIntPtr 将提供可以通过未管理的呼叫来圆形绕的手柄地址。实际对象地址将由 AddrOfPinnedObject 方法。

这一切,IMO,您的代码可能会将.NET对象与不受管理的对象相关联。这是因为gchandle.to/fromintptr将使您恢复正确的gchandle,并且您可以通过它到达.NET对象(前提是其未收集的垃圾)。 IMO,如果实际对象地址已更改,则应该是无关紧要的。

其他提示

当GC移动对象时,您将需要固定GCHANDLE以阻止对象移动,因此未添加的指针可能变得无效。固定对象停止它移动:

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

完成后,您还必须释放手柄:

handle.Free();

您得到的实际上不是一个地址。

当您注意到,它似乎大部分时间都像一个地址,并且您可以使用gchandle.fromintptr回想起对象。但是,有趣的问题是您正在使用 gchandletype.weaktrackrackursection.

如果您的弱引用的对象被收集(大概可以,因为它仅由gchandle引用),则您仍然具有INTPTR,您可以将其传递给 gchandle.fromintptr(). 。如果您这样做,那么假设INTPTR尚未回收,那么您将获得零。

(如果出于某种原因,INTPTR已被CLR回收,那么您会遇到麻烦。我不确定这是否会发生。)

您最好使用这两个 gchandletype。正常, , 或者 gchandletype.pinned (如果您需要在未托管的代码中获取对象的地址),如果您想对对象进行强有力的引用。

(要使用gchandletype。

afaik地址不会因为分配而改变,这是真的

托管对象的地址 改变。垃圾收集器可以自由移动内存中的对象。当垃圾收集器运行时,它会收集未使用的对象,然后重新安排剩余的对象,以最大程度地减少托管堆的整体尺寸。

有人有更好的主意来服务我的目标吗?

我不确定您会找到一种很好的方法,可以长时间保留托管对象的指针。可以将对象固定在内存中,并以这种方式获取其地址,但是在C#中,只能在单个方法中固定对象。

如果您更详细地解释了一旦将指针进行处理,这将有所帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top