4

我正在尝试调试多线程代码的一些奇怪行为,我需要一些方法来可靠地跟踪对象身份。在 C++ 中,我只需获取对象地址并将它们转换为字符串,这样我就可以知道这两个地址是否属于同一个对象。

看起来引用完全等同于 C# 中的 C++ 对象地址。

我可以将引用转换为字符串地址表示吗?

4

3 回答 3

3

您可以将引用转换为指针,然后转换为数字,但这不是在 C# 中跟踪对象的可靠方法,因为垃圾收集器可以随时更改引用。从引用中复制值后,您无法知道它仍然代表引用。

但是,您可以安全地比较参考。只要引用仍然是引用,垃圾收集器就会确保它是最新的。如果垃圾收集器移动了一个对象,它会更新对它的所有引用。

因此,您可以安全地将引用用作对象的标识,只要您将其保留为引用即可。您可以比较两个引用以查看它们是否指向同一个对象。

如果您将引用的值转换为不同的形式,您将获得当时引用的闪存副本。虽然查看该值可能仍然有用,但它不是 100% 可靠的,即仅仅因为两个引用的表示不同并不意味着它们不能指向同一个对象,因为引用可能在复制之间发生了变化第一个和第二个。

也就是说,您可以通过以下方式获取指向对象的指针并将其转换为IntPtr:

string str = "asdfasdf";
IntPtr p;

unsafe {
  // tell GC not to move the object, so that we can use a pointer to it
  fixed (void* ptr = str) {
    // here the object stays in place
    // make an IntPtr from the pointer, so we can keep it outside the fixed block
    p = new IntPtr(ptr);
  }
  // now the object can move again
}

Console.WriteLine(p);
于 2012-11-06T09:18:17.783 回答
0

创建一个ConditionalWeakTable<Object,String>,并且任何时候您看到不在表中的每个对象都给它某种名称并将其存储在表中。然后,您可以轻松地使用表格打印出您以前见过的任何对象的名称。如果一个对象不复存在,表项就会消失,因此不必担心表中会填满与早已被遗弃的对象相关的信息。

于 2014-01-07T20:30:36.523 回答
0

在某种程度上,您可以:

GCHandle.Alloc(obj, GCHandleType.Pinned).AddrOfPinnedObject().ToString();

请不要将此作为调试多线程应用程序的一种方式。按照达米安的指示去做。

于 2012-11-06T09:24:12.987 回答