代码之家  ›  专栏  ›  技术社区  ›  Paul Sasik

显示对象引用的值

  •  2
  • Paul Sasik  · 技术社区  · 14 年前

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

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

    在.NET中是否有类似的方法?

    这样做的价值只能是教育性的,例如为了展示一个价值,让学生看到,而不是仅仅比较参考平等或空值(无),以证明肤浅的副本、不变性等。

    7 回复  |  直到 11 年前
        1
  •  6
  •   Brian Rasmussen    14 年前

    如果这是为了教育目的,我建议您改用调试器。如果将sos.dll(是.NET框架的一部分)加载到windbg甚至Visual Studio中,则可以检查内存中的实际对象。

    例如,要列出堆,请使用 !dumpheap -stat 命令。这个 !do 命令将管理对象转储到指定的内存地址等。SoS有许多命令可以让您检查内部.NET结构,因此它是一个非常有用的工具,可以了解更多关于运行时的信息。

    通过使用调试器,您不必局限于查看演示应用程序。您可以查看真实应用程序的详细信息。此外,您还将学习一些非常有用的调试技巧。

    对使用windbg+sos进行调试有几个很好的介绍。检查 Tess' blog 很多教程。

        2
  •  7
  •   Ron Warholic    14 年前

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

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

    但请记住 格兰德尔 将仅固定属于基本类型或可浮动类型的对象。有些对象是可浮动的(您可以将其设置为演示目的,这样它就可以工作),但任何引用类型都是不可浮动的。

    您需要使用 [StructLayout(LayoutKind.Sequential)] 或者使用调试器直接检查不符合这些条件的对象的地址。

        3
  •  3
  •   Matthew Flaschen    14 年前

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

    “runtimehelpers.gethashcode很有用 在你关心的情况下 对象标识。两个字符串 相同的内容将返回 的不同值 RuntimeHelpers.GetHashCode,因为 它们是不同的字符串对象, 尽管它们的内容是相同的。”

    字符串文本的内接是主要的例外。这在C++中实际上是相同的。

        4
  •  0
  •   davbryn    14 年前

    我理解如果你提供编译器 /不安全 选项,将允许您编写“不安全”代码,并使用它可以访问指针。

    我没有测试过这个,但是找到了 in this artice

    编辑:

    似乎要记住的主要事情是,您必须用 unsafe 关键词:

    unsafe public static void Main()
    
        5
  •  0
  •   Jowen    14 年前

    在.NET中,根本不使用指针。因此,您将创建引用对象,其中的值始终可见。

    比较引用对象时,将比较引用,而不是实际值!(除了比较字符串,其中“==”已过载)。

    也许你想演示的.NET示例会详细说明…

        6
  •  0
  •   Tim Robinson    14 年前

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

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

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

    垃圾收集器的存在是 int* @jesper's中的指针存在于 { } 块。指针只固定在该块中;一旦执行离开该块,对象就有权被收集和/或移动。

        7
  •  -2
  •   Jesper Palm    14 年前
    unsafe 
    {
        object o = new Object(); 
        int *ptr = &o; //Get address
    
        Console.WriteLine((int)ptr); //Write address
    }
    

    您需要用/unsafe开关编译这个