在C++中,显示指向对象的指针的实际值非常简单。例如:显示对对象引用的值
void* p = new CSomething();
cout << p;
有没有办法在.NET中做这样的事情?
这样做的价值只能是教育性的,例如,为了演示的目的,在显示一个值的学生看到,而不是仅仅比较参考平等或空(无)证明浅拷贝,不变性等。
在C++中,显示指向对象的指针的实际值非常简单。例如:显示对对象引用的值
void* p = new CSomething();
cout << p;
有没有办法在.NET中做这样的事情?
这样做的价值只能是教育性的,例如,为了演示的目的,在显示一个值的学生看到,而不是仅仅比较参考平等或空(无)证明浅拷贝,不变性等。
编译这个如果这是教育的目的,我建议您改用调试器。如果将SOS.dll(它是.NET框架的一部分)加载到WinDbg甚至Visual Studio中,则可以检查内存中的实际对象。
E.g.列出堆使用!dumpheap -stat
命令。 !do
命令在指定的内存地址上转储管理对象等等。 SOS有许多命令可以让你检查内部的.NET结构,所以它是一个非常有用的工具,用于了解更多关于运行时的信息。
通过使用此调试器,您不受限于查看演示应用程序。您可以查看实际应用程序的细节。此外,你会拿起一些真正有用的调试技巧。
有几个很好的介绍使用WinDbg + SOS进行调试。检查Tess' blog有很多教程。
我明白,如果你提供编译器/不安全选项,你将被允许编写'不安全'的代码,并有权访问指针。
我没有测试过这一点,但发现它in this artice
编辑:
记得好像最主要的是,你将不得不使用不安全的代码与unsafe
关键字标记的任何代码:
unsafe public static void Main()
RuntimeHelpers.GetHashCode会给你一个基于身份的哈希码。实际上,这可能是基于地址。正如所解释的:
,你关心 对象的身份“RuntimeHelpers.GetHashCode是有用 在方案中两个字符串 相同的内容将返回 不同的值 RuntimeHelpers.GetHashCode,因为 它们是不同的字符串对象。 , 虽然他们的内容是相同的。“
实习字符串文字是主要的可能的例外。这在C++中实际上是一样的。
我不确定你为什么会陷入低谷。当然你的答案是不同的,但这是思考的好去处。的确,Object.GetHashCode()(RuntimeHelpers使用的)是基于对象在内存中的位置,因为这是该级别对象的唯一独特方面。在调试过程中,我经常会调用Object.GetHashCode()来验证两个引用是否指向同一个对象。 – 2010-07-28 18:14:46
在.NET中,你根本不用指针。所以你会创建引用对象,你可以随时看到它的值。
比较参考对象时,比较参考,而不是实际值! (除了比较字符串,其中'=='被重载)。
也许你想证明将阐述什么事情的.NET示例...
unsafe
{
object o = new Object();
int *ptr = &o; //Get address
Console.WriteLine((int)ptr); //Write address
}
您需要用/不安全开关
不起作用。它会给[CS0208](http://msdn.microsoft.com/en-us/library/x2estayf%28VS.80%29.aspx),“无法获取地址,获取大小或声明指针到托管类型('类型')“。 &运算符不能应用于托管类型。 – 2010-07-28 18:05:31
我认为这需要:'fixed(int * ptr =&o){...}' – 2010-07-28 18:09:24
@Tim,no。 '&o'在所有情况下都是无效的。 – 2010-07-28 18:14:36
您可以使用GCHandle
来获取固定对象的地址。 GC可以移动物体,所以唯一明智的地址是固定物体。
GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
Console.WriteLine(handle.AddrOfPinnedObject().ToInt32());
handle.Free();
请记住,GCHandle
只会固定原始类型或blittable类型的对象。一些对象是blittable(你可以设置它为演示目的,所以它的工作原理),但任何引用类型不会blittable。
您需要使用[StructLayout(LayoutKind.Sequential)]
添加明确的blittable描述,或者使用调试器直接检查不符合这些条件的对象的地址。
您可以在.NET中检索对象的地址,例如使用不安全的代码,但您获取的地址只是临时的 - 它将成为您接收地址的快照。
下一次垃圾收集情况,你的对象的地址可能会改变:
垃圾收集器的存在是为什么int*
指针在@的Jesper在一个{ }
块的范围存在的原因。指针仅在该块内固定;一旦执行离开块,该对象有权被收集和/或移动。
不安全的代码不会让您拥有指向托管类型的指针。请参阅[修复](http://msdn.microsoft.com/en-us/library/f58wzh21%28v=VS.71%29.aspx)文档。 – 2010-07-28 18:01:58