「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
LOHの問題によってGen2の断片化に起因するメモリリークが発生することもある(.NET3.5までの問題)。
久しぶりに使ったので手順などをメモ(幾つか補足も記載)。
※ 同様の操作をマネージ・ダンプに対して行う事もできる。
以下はSOSデバッガ拡張コマンドの実行例。
.load sos マネージのみのデバッグ中は、SOS は使用できません。 SOS を読み込むには、プロジェクト プロパティのアンマネージ デバッグを有効にしてください。
拡張 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll は読み込まれました
!DumpHeap [<-stat>] [-min <size>] [-max <size>] [-thinlock]~ [-mt <Method Table address>] [-type <partial type name>] [start[end]]
!DumpHeap -Type Class1
PDB symbol for mscorwks.dll not loaded
 Address       MT     Size
013ac060 009e71fc       20     
total 1 objects
Statistics:
      MT    Count    TotalSize Class Name
009e71fc        1           20 WindowsFormsApplication1.Class1
Total 1 objects!DumpObj <Object address>
!DumpObj 013ac060
Name: WindowsFormsApplication1.Class1
MethodTable: 009e71fc
EEClass: 00f01fb8
Size: 20(0x14) bytes
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79332d70  4000006        4         System.Int32  1 instance        9 a
79332d70  4000007        8         System.Int32  1 instance        9 b
79332d70  4000008        c         System.Int32  1 instance        9 c
79332d70  4000009       24         System.Int32  1   static        9 x
79332d70  400000a       28         System.Int32  1   static        9 y
79332d70  400000b       2c         System.Int32  1   static        9 z
DumpObj?に指定したオブジェクトのアドレスから
メモリ情報([メモリ] ウィンドウ)を確認すると
メンバ変数の情報を確認することができる。
!DumpClass <EEClass address>
!DumpClass 00f01fb8
Class Name: WindowsFormsApplication1.Class1
Parent Class: 790c3ef0
Module: 009e2c5c
Method Table: 009e71fc
Vtable Slots: 4
Total Method Slots: 6
Class Attributes: 100001  
NumInstanceFields: 3
NumStaticFields: 3
      MT    Field   Offset                 Type VT     Attr    Value Name
79332d70  4000006        4         System.Int32  1 instance           a
79332d70  4000007        8         System.Int32  1 instance           b
79332d70  4000008        c         System.Int32  1 instance           c
79332d70  4000009       24         System.Int32  1   static        9 x
79332d70  400000a       28         System.Int32  1   static        9 y
79332d70  400000b       2c         System.Int32  1   static        9 z
こちらでは、インスタンス変数の値は表示されない。
また、上記のフィールド情報はilasmを使用して確認できるらしいが、情報を確認できず。
!DumpModule <Modul address>
!DumpModule 009e2c5c Attributes: PEFile Assembly: 001b2478 LoaderHeap: 00000000 TypeDefToMethodTableMap: 009e00c0 TypeRefToMethodTableMap: 009e00dc MethodDefToDescMap: 009e0194 FieldDefToDescMap: 009e01d4 MemberRefToDescMap: 009e0204 FileReferencesMap: 009e02dc AssemblyReferencesMap: 009e02e0 MetaData start address: 00402440 (4084 bytes)
インスタンス
└メソッドテーブル ┬ EEClass ─ BaseClass
                   ├ MT of BaseClass
                   └ Module ┬ Field Descriptor Map
                             └ TypeDef To Method Table Map!DumpMT -md <Method Table address>(-mdを付与しないと一覧情報が出力されない)
!DumpMT -md 009e71fc EEClass: 00f01fb8 Module: 009e2c5c Name: WindowsFormsApplication1.Class1 mdToken: 02000006 BaseSize: 0x14 ComponentSize: 0x0 Number of IFaces in IFaceMap: 0 Slots in VTable: 6 -------------------------------------- MethodDesc Table Entry MethodDesc JIT Name 79286aa0 79104944 PreJIT System.Object.ToString() 79286ac0 7910494c PreJIT System.Object.Equals(System.Object) 79286b30 7910497c PreJIT System.Object.GetHashCode() 792f7510 791049a0 PreJIT System.Object.Finalize() 009ec160 009e71e4 JIT WindowsFormsApplication1.Class1..ctor() 009ec168 009e71f0 JIT WindowsFormsApplication1.Class1..cctor()
!DumpHeap -stat
total 10311 objects
Statistics:
      MT    Count    TotalSize Class Name
・・・
009e6c90        1           20 WindowsFormsApplication1.Class1
・・・
009e5e50        1          332 WindowsFormsApplication1.Form1!DumpHeap -mt 009e5e50
 Address       MT     Size
013bd8f4 009e5e50      332     
total 1 objects
Statistics:
      MT    Count    TotalSize Class Name
009e5e50        1          332 WindowsFormsApplication1.Form1
Total 1 objects!gcroot 013bd8f4 Note: Roots found on stacks may be false positives. Run "!help gcroot" for more info. ebx:Root:013be34c(System.Windows.Forms.Application+ThreadContext)-> 013bd8f4(WindowsFormsApplication1.Form1) esi:Root:013e0b2c(System.Windows.Forms.Application+ComponentManager+ComponentHashtableEntry)-> 013be34c(System.Windows.Forms.Application+ThreadContext) edi:Root:013eb4a0(System.Collections.Hashtable+HashtableEnumerator)-> 013e0b2c(System.Windows.Forms.Application+ComponentManager+ComponentHashtableEntry) Scan Thread 0 OSTHread 1a30 ESP:12f358:Root:013be34c(System.Windows.Forms.Application+ThreadContext)-> 013e0b2c(System.Windows.Forms.Application+ComponentManager+ComponentHashtableEntry) ESP:12f360:Root:013e0ae4(System.Windows.Forms.Application+ComponentManager)-> 013be34c(System.Windows.Forms.Application+ThreadContext) ・・・ 013dc328(Microsoft.Win32.UserPreferenceChangedEventHandler)-> 013bd8f4(WindowsFormsApplication1.Form1) DOMAIN(00159EE0):HANDLE(Pinned):9c13ec:Root:02333250(System.Object[])-> 013be278(System.Collections.Hashtable)-> 013be2b0(System.Collections.Hashtable+bucket[])-> 013be34c(System.Windows.Forms.Application+ThreadContext)
!eeheap -gc Number of GC Heaps: 1 generation 0 starts at 0x01331018 generation 1 starts at 0x0133100c generation 2 starts at 0x01331000 ephemeral segment allocation context: none segment begin allocated size 01330000 01331000 013ebff4 0x000baff4(765940) Large object heap starts at 0x02331000 segment begin allocated size 02330000 02331000 02336de8 0x00005de8(24040) Total Size 0xc0ddc(789980) ------------------------------ GC Heap Size 0xc0ddc(789980)
!objsize 013bd8f4 sizeof(013bd8f4) = 13420 ( 0x346c) bytes (WindowsFormsApplication1.Form1) ※ 単体:332、参照先を含める:13420
!finalizequeue
SyncBlocks to be cleaned up: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
generation 0 has 360 finalizable objects (001e7090->001e7630)
generation 1 has 0 finalizable objects (001e7090->001e7090)
generation 2 has 0 finalizable objects (001e7090->001e7090)
Ready for finalization 0 objects (001e7630->001e7630)
Statistics:
      MT    Count    TotalSize Class Name
7b2252dc        1           16 System.Windows.Forms.Control+FontHandleWrapper
7b226088        1           20 System.Windows.Forms.ApplicationContext
79321428        1           20 Microsoft.Win32.SafeHandles.SafePEFileHandle
7ae3ca3c        1           24 System.Drawing.Bitmap
7b226160        1           28 System.Windows.Forms.Cursor
・・・
009e5e50        1          332 WindowsFormsApplication1.Form1
7b2238c4       26          728 System.Windows.Forms.Internal.WindowsGraphics
7b21a930       20          960 System.Windows.Forms.Internal.WindowsPen
7932a41c       87         1392 System.WeakReference
7b223a00       26         1872 System.Windows.Forms.Internal.DeviceContext
Total 360 objects* e !clrstackで、全てのマネージスレッドとスタックトレースし、ファイナライザスレッドのハングを確認する。
~* e !clrstack OS Thread Id: 0x1a30 (0) ESP EIP 0012f32c 7c94e514 [InlinedCallFrame: 0012f32c] System.Windows.Forms.UnsafeNativeMethods.WaitMessage() 0012f328 7b1d8ed8 System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32) 0012f3c4 7b1d89c7 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext) 0012f418 7b1d8811 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext) 0012f448 7b195921 System.Windows.Forms.Application.Run(System.Windows.Forms.Form) 0012f45c 00f300ae WindowsFormsApplication1.Program.Main() 0012f688 79e71b4c [GCFrame: 0012f688] OS Thread Id: 0x1a44 (1) Unable to walk the managed stack. The current thread is likely not a managed thread. You can run !threads to get a list of managed threads in the process OS Thread Id: 0x16c8 (2) Failed to start stack walk: 80004005 OS Thread Id: 0xa14 (3) Unable to walk the managed stack. The current thread is likely not a managed thread. You can run !threads to get a list of managed threads in the process OS Thread Id: 0x11fc (4) Unable to walk the managed stack. The current thread is likely not a managed thread. You can run !threads to get a list of managed threads in the process
!Threads -special
ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                      PreEmptive   GC Alloc           Lock
       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception
   0    1 1a30 00161b98      6020 Enabled  013eb4c4:013ebfe8 00159ee0     0 STA
   2    2 16c8 0016e360      b220 Enabled  00000000:00000000 00159ee0     0 MTA (Finalizer)
       OSID     Special thread type
   1   1a44    DbgHelper 
   2   16c8    FinalizerWinDbgとSilverlightをインストールしておく。
以下WinDbgにてSilverlightのダンプファイルから、オブジェクト数を確認する手順の例。
アタッチ先を「iexplore.exe」などに設定すれば、ライブ・デバックも可能であるもよう。
.load C:\Program Files\Microsoft Silverlight\4.1.10329.0\sos.dll※パスは環境(インストール・バージョン、インストール先)に応じて修正してください
!dumpheap -stat
!dumpheap -stat -type XXXXXXX
Silverlight Toolkitにメモリリークの問題があります。
We encountered this bug too, but took a slightly different tact -- we used a weak event listener pattern.
           if (null != _rootVisual)
           {
               // Ideally, this would use AddHandler(MouseMoveEvent), but MouseMoveEvent doesn't exist
               _rootVisual.MouseMove += new MouseEventHandler(HandleRootVisualMouseMove);
           }           if (null != _rootVisual)
           {
               var rootVisual = _rootVisual;
               // Use a weak event listener.
               var rootVisualMouseMoveListener = new WeakEventListener<ContextMenu, object, MouseEventArgs>( this );
               rootVisualMouseMoveListener.OnEventAction = ( instance, source, eventArgs ) => instance.HandleRootVisualMouseMove( source, eventArgs );
               rootVisualMouseMoveListener.OnDetachAction = ( weakEventListener ) => rootVisual.MouseMove -= weakEventListener.OnEvent;
               rootVisual.MouseMove += rootVisualMouseMoveListener.OnEvent;
           }ここの「we used:」が修正コード。
Visual Studio2015 Enterprise Edition ではマネージ メモリの分析機能が
強化されており、!DumpHeap? コマンドで実現できることに近い内容が確認できる。
"マネージ型レポート"
.NET Framework アプリケーションのデバッグに有用
(ただし、サポートは提供されておらずドキュメントや公開情報も少ない状況)
.load "C:\\Psscor4\\x86\\x86\\psscor4.dll" !psscor4.help
.load mex.dll !mex.help