引用对象的地址在即时窗口中工作但不在编译代码中

时间:2012-09-28 17:09:04

标签: c# .net clr

所以我已经看过几次关于在C#中获取参考对象的物理地址的问题,并且普遍的共识似乎是这是不可能的,因为你不能用{GCHandle.Alloc来调用GCHandleType.Pinned {1}}这将允许您获取固定对象的地址。

我觉得奇怪的是,在Visual Studio调试器中,我可以将对象从locals窗口拖到Memory调试窗口,并查看引用对象的地址和内存。我甚至可以输入即时窗口&obj并获取对象的实际地址(该地址正确对应于“内存”窗口中显示的地址)。

但是为什么我不能在我的编译代码中进行相同的调用...即:

object someObject = new Object();
&obj; // Compiler Error: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object')

如何使用Immediate \ Memory Window获取托管类型的地址,甚至显示内存的布局,但C#不能执行任何操作?有没有办法在C#中获取引用对象的实际地址?

2 个答案:

答案 0 :(得分:2)

调试器比你自己的代码有很大的优势。它可以在运行 no 代码时冻结进程状态。因此,获取对象的地址不是问题,垃圾收集器不会运行以使其无效。

答案 1 :(得分:0)

Carbage Collector处理对象的生命周期。它在内存中大致分为3个“部分”,称为gen0,gen1,gen2(Generations)。

在gen0中,快速生存对象驻留,分配的内存很小。垃圾收集经常运行,因为那里有许多短期对象。如果一个对象使用gen0,它将被移动到下一代。

当一个对象被收集时,所有其他对象被重新安排在内存中,以保持可用的内存空间。

但是在gen2中,最大和最长寿命的对象存在,内存很少被重新排列,因为它在gen2中移动对象的成本太高。

所有这些内存引用和垃圾收集都是在C#等托管环境中为“免费”提供的。

此外,有时会进行优化,例如:“string interning”。