问题描述
我正在尝试追踪单声道运行时中的一个错误,其中一个变量似乎被分配给一个有效对象,然后被重新分配给一个虚假对象,特别是
I am trying to track down a bug in the mono runtime where a variable appears to be allocated to one valid object, and then is reassigned later to a bogus object, specifically
//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.
我想知道对o"的引用何时变得无意义,为此我正在寻找一种方法来确定 C# 代码中各个时间点的o"地址.我知道与其他问题类似,答案是不要这样做,有 GC",但 GC 不起作用,所以我需要一个解决方法.
I would like to know when the reference to "o" becomes nonsense, and to do this am looking for a way to determine the address of "o" at various timepoints within the C# code. I know is similar to other questions with answers "don't do that there is a GC", but the GC doesn't work so I need a workaround.
有谁知道如何确定 C# 中单声道对象的地址?可以链接非托管代码或其他任何内容.(任何其他线索来诊断主要问题的方法都值得赞赏).
Does anyone know how I can determine the address of a mono object in C#? Am fine to link in unmanaged code or whatever. (Any other clues to ways to diagnose the main issue appreciated to).
推荐答案
原来这在 .NET 中无法直接实现,但可以通过更改 mono 运行时代码来实现.要创建可以读取内存地址的 C# 方法,请对 mono 源代码进行以下更改:
Turns out this is not possible in .NET directly, but can be accomplished by altering the mono runtime code. To create a C# method that can read the memory address, make the following changes to the mono source code:
修改 gc-internal.h 以添加
Alter gc-internal.h to add
gpointer ves_icall_System_GCHandle_GetAddrOfObject (MonoObject *obj) MONO_INTERNAL;
更改 gc.c 以添加:
Alter gc.c to add:
gpointer ves_icall_System_GCHandle_GetAddrOfObject (MonoObject *obj) {
return (char*)obj;
}
更改 GCHandle.cs 以添加:
Alter GCHandle.cs to add:
MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static IntPtr GetAddrOfObject(object obj);
public static IntPtr AddrOfObject(object o)
{
IntPtr res = GetAddrOfObject(o);
return res;
}
修改 icall-def.h 以添加
Alter icall-def.h to add
ICALL(GCH_6, "GetAddrOfObject", ves_icall_System_GCHandle_GetAddrOfObject)
请注意,这些必须按顺序排列,因此将其添加到 GetAddrOfPinnedObject 行上方重建
Note that these must be in order, so add it above the GetAddrOfPinnedObject line Rebuild
最后,从 C# 调用它
Finally, call it from C#
for (int i = 0; i < 100; i++) {
object o = new object ();
var ptr = GCHandle.AddrOfObject (o);
Console.WriteLine ("Address: " + ptr.ToInt64().ToString ("x"));
}
这篇关于获取 .NET 对象的内存地址 (C#)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!