获取.NET对象的内存地址(C#)

evo*_*obe 7 c# mono garbage-collection

我试图追踪单声道运行时中的一个错误,其中一个变量似乎被分配给一个有效对象,然后被重新分配给一个虚假对象,特别是

//early in code I allocate, fine
var o = new object(); // valid allocation
// later in code this is called, not fine
lock(o) // <- is triggering bug due to "o" now referencing a nonsense memory location.
Run Code Online (Sandbox Code Playgroud)

我想知道何时对"o"的引用变得无意义,并且这样做是为了找到一种方法来确定C#代码中各个时间点的"o"的地址.我知道类似于其他问题的答案"不要做有GC",但GC不起作用所以我需要一个解决方法.

有谁知道如何在C#中确定单声道对象的地址?很好地链接在非托管代码或其他任何东西.(关于诊断主要问题的方法的任何其他线索).

s.b*_*rns 12

您应该能够使用GCHandle构造来实现此目的.

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

'obj'是你想要得到的地址的对象.

  • 'address'int应该对应于内存中的当前指针,该指针可能由于GC的标准内部存储器管理而改变.如果你需要一个固定的地址,你必须确保它是内存中的固定对象并使用'GCHandle.AddrOfPinnedObject(objHandle);' 而不是GCHandle.ToIntPtr(objHandle);. 请记住,GCHandle.Alloc()函数确保对象不会被内部内存管理收集垃圾,因此当不再需要该内存以防止泄漏时,您必须手动释放该内存. (2认同)

evo*_*obe 5

事实证明这在.NET中是不可能的,但可以通过改变单声道运行时代码来实现.要创建可以读取内存地址的C#方法,请对单声道源代码进行以下更改:

更改gc-internal.h

gpointer    ves_icall_System_GCHandle_GetAddrOfObject (MonoObject *obj) MONO_INTERNAL;
Run Code Online (Sandbox Code Playgroud)

改变gc.c添加:

gpointer    ves_icall_System_GCHandle_GetAddrOfObject (MonoObject *obj) {
    return (char*)obj;
}
Run Code Online (Sandbox Code Playgroud)

改变GCHandle.cs添加:

MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static IntPtr GetAddrOfObject(object obj);

public static IntPtr AddrOfObject(object o)
{
    IntPtr res = GetAddrOfObject(o);
    return res;
}
Run Code Online (Sandbox Code Playgroud)

改为添加icall-def.h

ICALL(GCH_6, "GetAddrOfObject", ves_icall_System_GCHandle_GetAddrOfObject)
Run Code Online (Sandbox Code Playgroud)

请注意,这些必须按顺序排列,因此请将其添加到GetAddrOfPinnedObject行重建之上

最后,从C#调用它

for (int i = 0; i < 100; i++) {
    object o = new object ();
    var ptr = GCHandle.AddrOfObject (o);
    Console.WriteLine ("Address: " + ptr.ToInt64().ToString ("x"));
}
Run Code Online (Sandbox Code Playgroud)