显示对象的引用值

时间:2010-07-28 17:48:48

标签: c# .net vb.net memory-management

在C ++中,显示指向对象的指针的实际值非常简单。例如:

void* p = new CSomething();
cout << p;

有没有办法在.NET中做这样的事情?

这样做的价值只会是教育性的,例如为了示范的目的,如显示学生看到的价值,而不仅仅是比较参考相等或无(无)证明浅拷贝,不变性等。

7 个答案:

答案 0 :(得分:7)

您可以使用GCHandle获取固定对象的地址。 GC可以移动对象,因此获取的唯一合理地址是固定对象之一。

GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
Console.WriteLine(handle.AddrOfPinnedObject().ToInt32());
handle.Free();

请记住,GCHandle只会固定原始或blittable类型的对象。某些对象是blittable(您可以将其设置为演示目的,因此它可以工作)但任何引用类型都不会是blittable。

您需要使用[StructLayout(LayoutKind.Sequential)]添加显式的blittable描述,或使用调试器直接检查不符合这些条件的对象的地址。

答案 1 :(得分:6)

如果这是出于教育目的,我建议您使用调试器。如果您将SOS.dll(它是.NET框架的一部分)加载到WinDbg甚至Visual Studio中,您可以检查内存中的实际对象。

E.g。列出堆使用!dumpheap -stat命令。 !do命令将指定内存地址上的管理对象转储,依此类推。 SOS有许多命令可以让你检查内部的.NET结构,所以它是一个非常有用的工具,可以学习更多有关运行时的知识。

通过使用调试器,您不仅限于查看演示应用程序。您可以查看实际应用程序的详细信息。此外,您将获得一些非常有用的调试技巧。

使用WinDbg + SOS进行调试有几个很好的介绍。查看Tess' blog了解大量教程。

答案 2 :(得分:3)

RuntimeHelpers.GetHashCode将为您提供基于身份的哈希码。实际上,这可能是基于地址。如上所述:

  

“RuntimeHelpers.GetHashCode非常有用   在你关心的场景中   对象身份。两个字符串   相同的内容将返回   不同的价值观   RuntimeHelpers.GetHashCode,因为   它们是不同的字符串对象,   虽然他们的内容是一样的。“

字符串文字的实习是主要的可能例外。这在C ++中实际上是相同的。

答案 3 :(得分:0)

据我所知,如果您为编译器提供 / unsafe 选项,您将被允许编写“不安全”代码,并且可以使用它来访问指针。

我没有对此进行过测试,但发现它in this artice

编辑:

似乎要记住的主要事情是,您必须使用unsafe关键字的不安全代码标记任何代码:

unsafe public static void Main()

答案 4 :(得分:0)

在.Net中你根本不使用指针。因此,您将创建参考对象,您始终可以看到该值。

比较参考对象时,会比较参考,而不是实际值! (除了比较字符串,'=='超载)。

也许你要展示的一个.Net例子会详细说明......

答案 5 :(得分:0)

您可以在.NET中检索对象的地址,例如使用不安全的代码,但您获取的地址只是临时的 - 它将是您获取地址的快照。 / p>

下次发生垃圾收集时,对象的地址可能会发生变化:

  • 如果对象不再从任何地方引用,它将被收集,而其他一些对象将占用该地址
  • 如果仍然引用该对象,它可能会被提升为更高代(因此移动到不同的GC堆)。或者,如果它已经在第2代,它可能会随着堆的压缩而在内存中移动。

垃圾收集器的存在是@ Jesper中int*指针存在于{ }块范围内的原因。指针仅在该块内固定;一旦执行离开块,该对象有权被收集和/或移动。

答案 6 :(得分:-2)

unsafe 
{
    object o = new Object(); 
    int *ptr = &o; //Get address

    Console.WriteLine((int)ptr); //Write address
}

您需要使用/ unsafe开关

进行编译