軟件安裝
安裝問題:執行 .loadby sos clr 命令無效
解決辦法:
.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
執行結果:
進入線程
命令: ~~[線程Id]s
執行結果:
查看線程詳情
命令: !clrstack
執行結果:
查看線程狀態
命令: !ThreadState 線程StateId
執行結果:
退出附加進程
命令: qd
查看線程環境塊(空間)
命令: !Teb
執行結果:
查看線程堆棧
命令: !dumpstack
執行結果:
查看局部變量
命令: !clrstack
!clrstack -l
執行結果:
查看幫助
命令: !help
執行結果:
查看終結器隊列
命令: !FinalizeQueue
執行結果:
查看線程池詳情
命令: !threadpool
執行結果:
查看查看當前托管線程已執行時間
命令: !runaway
執行結果:
清屏
命令: !cls
查看查看當前托管線程已執行時間
命令: ~*e!clrstack
執行結果:看所有線程的堆棧
CPU過高的問題
模擬CPU過高
示例代碼:
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:
解決CUP占用過高
創建轉儲文件:
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
找到該轉儲文件: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“ 我們就找出了問題。。。