我得到了一些託管進程的大量內存轉儲,我試圖從堆中獲取大量統計信息 - 以及能夠呈現交互式視圖 - 相當深的對象圖。想象一下與!do <address>
相似的東西與SOS設置在WinDbg中,在那裏你可以不斷點擊屬性並查看它們的值,只是在一個非常友好的用戶界面中比較許多對象。如何使用ClrMD正確處理非原始ClrInstanceField值?
我發現Microsoft.Diagnostics.Runtime(ClrMD)是特別適合這項任務,但我有一個困難時期陣列領域的工作和我有點困惑對象字段,我有更好的工作。
陣列: 如果我的目標和地址的陣列直接關閉堆和使用ClrType.GetArrayLength
和ClrType.GetArrayElementValue
事情做工精細,但一旦我通過另一個對象的字段挖,我不當然ClrInstanceField.ElementType
是ClrElementType.SZArray
(我還沒有遇到Array
在我的對象圖中挖掘,但我也想處理它),我從ClrInstanceField.GetValue
得到什麼值。
編輯:我只是決定使用ClrType
爲System.UInt64
取消引用數組字段(使用parent address + offset of the array field
來計算,其中陣列的指針存儲在地址),那麼我可以與它的工作方式相同,如果我從EnumerateObjects獲得它。我現在遇到了一些不支持ArrayComponentType
屬性的陣列。我還沒有用Structs數組進行測試,所以我也想知道它是否是C樣式的嵌入式結構分配,就像int[]
或者它是堆中結構的指針數組。 Guid[]
是我遇到從ArrayComponentType
獲取問題的類型之一。
對象:固定(邏輯錯誤)
隨着
ClrInstanceField
擁有的
ClrElementType.Object
我得到更好的結果
Type
,但仍需要更多一點。首先,在撥打
GetFieldValue
後,我得到了一個
ulong
地址(?),我可以使用
ClrInstanceField.Type.Fields
來對付,所以我可以看到嵌套對象的字段名稱和值。也就是說,我必須考慮多態性,所以我嘗試在同一地址上使用
ClrHeap.GetObjectType
,並且它返回NULL或者完全不正確。這個地址在我的第一個用例中起作用似乎很奇怪,但不是第二個。
字符串:固定(找到解決方法)
因爲我真正的項目已經使用DbgEng W/SOS,我有不同的方法可以輕鬆地獲得通過地址字符串的值,但它似乎很奇怪,試圖使用
ClrInstanceField.GetFieldValue
成功返回一個字符串,但結果完全不準確(一堆奇怪的字符)。也許我做錯了?
編輯:我已經提取,現在在LINQPad從我原來的代碼運行的抽象。在這裏發佈會有點長,但全部都是here in a gist。從所有的複製/粘貼/重構中來看,它仍然有點混亂,我會在進一步清理它之後,在解決這些問題後,在CodePlex或GitHub上發佈最終源代碼。
代碼庫相當大,特定於某個項目,但如果絕對必要,我可能能夠提取出樣本集。也就是說,所有對ClrMD對象的訪問都非常簡單。我從SOS命令中獲得初始地址,如
!dumpheap -stat
(對根對象工作正常),然後使用
ClrHeap.GetTypeByName
或
ClrHeap.GetObjectType
。之後,它完全依靠
ClrType.Fields
和
ClrInstanceField
成員
Type
,
ElementType
和
GetFieldValue
作爲額外的獎勵,我沒有找到一個browser friendly版本提供的NuGet包的XML文檔,雖然它是相同的文檔的IntelliSense提供。
我已經在ClrMD之上創建了一個擴展庫,與LINQPad很好地整合,如果您感興趣,請檢查下列內容: https://github.com/JeffCyr/ClrMD.Extensions –