【问题标题】:Is it possible to get the string representation of C# object address?是否可以获得 C# 对象地址的字符串表示形式?
【发布时间】:2012-10-26 05:01:43
【问题描述】:

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

在 C# 中看起来像 a reference is a full equivalent 的 C++ 对象地址。

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

【问题讨论】:

  • ReferenceEquals 有什么问题?如果是跨时间比较,那当然是行不通的,因为 .NET 对象会因 GC 而移动。
  • @Damien_The_Unbeliever:这将需要一些内部对象列表和内部比较。我宁愿只查看日志并从中得出结论。
  • 那么,这是跨时间的比较吗?
  • 使用unsafe关键字。
  • @Damien_The_Unbeliever:我只需要在日志中有地址就可以方便地编写大量额外代码来维护列表并查找哪个对象是哪个对象。我需要一些 C++ printf("%p") 的直接等价物。

标签: c# reference identity


【解决方案1】:

您可以将引用转换为指针,然后转换为数字,但这不是在 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);

【讨论】:

  • 好吧,编译器说它不会将object隐式编译为void*
  • @sharptooth:是的……它对不同的数据类型有点不同……我实际上用一个字符串测试了它,就是这样。
【解决方案2】:

在某种程度上,你可以:

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2022-01-12
      • 1970-01-01
      • 2019-11-11
      • 2011-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-27
      相关资源
      最近更新 更多