安裝問題:執行 .loadby sos clr 命令無效數組
解決辦法:dom
.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll .load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll .loadby sos clr
命令: !threads ui
執行結果:this
命令: ~~[線程Id]s spa
執行結果:線程
命令: !clrstack 3d
執行結果:調試
命令: !ThreadState 線程StateId code
執行結果:blog
命令: qd
命令: !Teb
執行結果:
命令: !dumpstack
執行結果:
命令: !clrstack
!clrstack -l
執行結果:
命令: !help
執行結果:
命令: !FinalizeQueue
執行結果:
命令: !threadpool
執行結果:
命令: !runaway
執行結果:
命令: !cls
命令: ~*e!clrstack
執行結果:看全部線程的堆棧
示例代碼:
class Program { static void Main(string[] args) { Run(); Console.Read(); } static void Run() { var task = Task.Factory.StartNew(() => { //這是一個很是複雜的邏輯,致使死循環 while (true) { } }); } }
生成64位Realease版本代碼:
在Bin/Realse下找到文件並運行,而後查看CPU:
建立轉儲文件:
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
找到該轉儲文件:C:\Users\ADMINI~1\AppData\Local\Temp\ConsoleApp4.DMP
用X64版本的WinDbg打開DMP文件:
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
而後打開命令輸入:
而後輸入 .loadby sos clr 與 !threads
如今線程少沒有關係,多的話咱們沒有辦法去判斷哪一個線程消耗嚴重,因此執行 !runaway 查看當前託管線程已執行時間
切換到指定線程 ~~[4f78]s ,執行 !clrstack 查看當前線程的調用堆棧
從調用堆棧上來看,當前線程 在 Program+c.b__1_0() 方法以後23行就沒有調用堆棧了,說明方法在這個地方停滯不前了。
最後反編譯源碼到指定的方法中去查看
方法二:
經過 !dumpdomain 拿到程序地址
而後反編譯成dll輸出文件 !savemodule 00007ff7e4f94120 c:\2\1.dll (文件夾必須存在)
而後找到該dll進行反編譯
實例代碼:
class Program { static void Main(string[] args) { new Program().Run(); Console.Read(); } void Run() { lock (this) { var task = Task.Factory.StartNew(() => { Console.WriteLine("-------start-------"); Thread.Sleep(1000); Run2(); Console.WriteLine("---------end--------"); }); task.Wait(); } } void Run2() { lock (this) { Console.WriteLine("------我是Run2------"); } } }
執行結果:
而後用WinDbg附加到進程,執行 .loadby sos clr 與 !threads 查看當前的託管線程
而後執行 ~*e!clrstack 查看全部線程的堆棧
能夠看出主線程在等待
執行 !syncblk 查看當前哪一個線程持有鎖,能夠看出主線程持有鎖
能夠看得出「主線程」持有當前的同步鎖
實例代碼:
class Program { static StringBuilder sb = new StringBuilder(); static void Main(string[] args) { for (int i = 0; i < 10000000; i++) { sb.Append("hello world"); } Console.WriteLine("執行完畢"); Console.Read(); } }
而後用WinDbg附加到進程,執行 .loadby sos clr 與 !threads ,而後執行 !dumpheap -stat 查看clr的託管堆中的各個類型的佔用狀況
而後看到了有13768個char[]數組
而後執行 !DumpHeap /d -mt 00007ff841318610 //查看當前的方法表
而後執行 !DumpObj /d 0000022baed1dec8 //查看當前char[]的內容
而後執行 !gcroot 00000135a60f4940 查看當前地址的Root。。。
因此結合「StringBuilder」,結合 」hello world「 咱們就找出了問題。。。