2010-07-28 53 views
2

在C++中,顯示指向對象的指針的實際值非常簡單。例如:顯示對對象引用的值

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

有沒有辦法在.NET中做這樣的事情?

這樣做的價值只能是教育性的,例如,爲了演示的目的,在顯示一個值的學生看到,而不是僅僅比較參考平等或空(無)證明淺拷貝,不變性等。

回答

6

編譯這個如果這是教育的目的,我建議您改用調試器。如果將SOS.dll(它是.NET框架的一部分)加載到WinDbg甚至Visual Studio中,則可以檢查內存中的實際對象。

E.g.列出堆使用!dumpheap -stat命令。 !do命令在指定的內存地址上轉儲管理對象等等。 SOS有許多命令可以讓你檢查內部的.NET結構,所以它是一個非常有用的工具,用於瞭解更多關於運行時的信息。

通過使用此調試器,您不受限於查看演示應用程序。您可以查看實際應用程序的細節。此外,你會拿起一些真正有用的調試技巧。

有幾個很好的介紹使用WinDbg + SOS進行調試。檢查Tess' blog有很多教程。

0

我明白,如果你提供編譯器/不安全選項,你將被允許編寫'不安全'的代碼,並有權訪問指針。

我沒有測試過這一點,但發現它in this artice

編輯:

記得好像最主要的是,你將不得不使用不安全的代碼與unsafe關鍵字標記的任何代碼:

unsafe public static void Main() 
+0

不安全的代碼不會讓您擁有指向託管類型的指針。請參閱[修復](http://msdn.microsoft.com/en-us/library/f58wzh21%28v=VS.71%29.aspx)文檔。 – 2010-07-28 18:01:58

3

RuntimeHelpers.GetHashCode會給你一個基於身份的哈希碼。實際上,這可能是基於地址。正如所解釋的:

,你關心 對象的身份「RuntimeHelpers.GetHashCode是有用 在方案中兩個字符串 相同的內容將返回 不同的值 RuntimeHelpers.GetHashCode,因爲 它們是不同的字符串對象。 , 雖然他們的內容是相同的。「

實習字符串文字是主要的可能的例外。這在C++中實際上是一樣的。

+0

我不確定你爲什麼會陷入低谷。當然你的答案是不同的,但這是思考的好去處。的確,Object.GetHashCode()(RuntimeHelpers使用的)是基於對象在內存中的位置,因爲這是該級別對象的唯一獨特方面。在調試過程中,我經常會調用Object.GetHashCode()來驗證兩個引用是否指向同一個對象。 – 2010-07-28 18:14:46

0

在.NET中,你根本不用指針。所以你會創建引用對象,你可以隨時看到它的值。

比較參考對象時,比較參考,而不是實際值! (除了比較字符串,其中'=='被重載)。

也許你想證明將闡述什麼事情的.NET示例...

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

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

您需要用/不安全開關

+0

不起作用。它會給[CS0208](http://msdn.microsoft.com/en-us/library/x2estayf%28VS.80%29.aspx),「無法獲取地址,獲取大小或聲明指針到託管類型('類型')「。 &運算符不能應用於託管類型。 – 2010-07-28 18:05:31

+0

我認爲這需要:'fixed(int * ptr =&o){...}' – 2010-07-28 18:09:24

+0

@Tim,no。 '&o'在所有情況下都是無效的。 – 2010-07-28 18:14:36

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描述,或者使用調試器直接檢查不符合這些條件的對象的地址。

0

您可以在.NET中檢索對象的地址,例如使用不安全的代碼,但您獲取的地址只是臨時的 - 它將成爲您接收地址的快照。

下一次垃圾收集情況,你的對象的地址可能會改變:

  • 如果對象不再從任何地方引用,它會被收集,以及其他一些對象將佔用地址
  • 如果該對象仍在被引用,它可能會被提升到更高一代(因此被移動到不同的GC堆)。或者,如果它已經在第2代,它可能會因爲堆壓縮而移動到內存中。

垃圾收集器的存在是爲什麼int*指針在@的Jesper在一個{ }塊的範圍存在的原因。指針僅在該塊內固定;一旦執行離開塊,該對象有權被收集和/或移動。