Windows 調(diào)試工具課程,在軟件崩潰中調(diào)試出原因
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
本文是我在集團(tuán)內(nèi)部上的課程記錄而成的博客內(nèi)容。在本次課程里面將和大家介紹一些在 Windows 上常用的調(diào)試工具,以及調(diào)查問(wèn)題的常見(jiàn)套路。適合于伙伴們?nèi)腴T(mén) Windows 調(diào)試 本文以下內(nèi)容是采用原本課程課件里面的一頁(yè)頁(yè)的內(nèi)容組裝而來(lái),過(guò)程中補(bǔ)充一些講課時(shí)的內(nèi)容 本次課程里面核心的內(nèi)容是調(diào)試工具,調(diào)試工具是我們?cè)谡{(diào)試軟件的時(shí)候的利器,通過(guò)調(diào)試工具我們可以找到軟件的問(wèn)題,解決軟件的問(wèn)題 本次的課程的開(kāi)始我來(lái)和大家講一個(gè)調(diào)試故事,這個(gè)故事是從用戶反饋軟件用不了的問(wèn)題開(kāi)始的 用戶說(shuō)軟件用不了,那可能會(huì)是什么問(wèn)題呢?用戶不是專業(yè)的開(kāi)發(fā)人員,他們不知道如何準(zhǔn)確的表述問(wèn)題 學(xué)過(guò)軟件工程的同學(xué)應(yīng)該有不少,軟件工程里面應(yīng)該會(huì)有提到,開(kāi)發(fā)的第一步也是非常關(guān)鍵的一步就是需求分析。當(dāng)收到用戶反饋說(shuō)軟件用不了時(shí),用戶在說(shuō)什么呢?是不是可能是軟件崩潰了?還是軟件無(wú)法啟動(dòng)?還是其他的問(wèn)題 遇到用戶說(shuō)軟件用不了的時(shí)候,咱可以有哪些入手點(diǎn)呢?我的調(diào)查思路是分為兩個(gè)大的方向。第一個(gè)方向是從當(dāng)下的情況入手。如果當(dāng)下已經(jīng)沒(méi)有了現(xiàn)場(chǎng)了,則可以考慮第二個(gè)方向,復(fù)現(xiàn)(重現(xiàn))問(wèn)題 從第一個(gè)方向入手時(shí),可以先考慮從用戶的設(shè)備上尋找痕跡。接下來(lái)我將和大家聊聊如何開(kāi)始從用戶的設(shè)備上尋找痕跡。當(dāng)然了,如果這個(gè)用戶是咱的測(cè)試人員或者是咱的同事,那尋找痕跡這一步就更有價(jià)值了 在用戶設(shè)備上尋找痕跡時(shí),別忘了 Windows 是咱的好朋友。Windows 提供了很多工具,可以幫助我們找到問(wèn)題的原因。接下來(lái)我將和大家介紹一些 Windows 上自帶的常用的調(diào)試工具 第一站就是事件查看器??梢韵燃僭O(shè)咱可能遇到的是軟件啟動(dòng)即崩潰的問(wèn)題。在不遠(yuǎn)程用戶的情況下,可以先請(qǐng)用戶發(fā)送系統(tǒng)事件日志或截圖過(guò)來(lái)看看。事件查看器作為第一站的原因是可不發(fā)起遠(yuǎn)程,直接請(qǐng)用戶截圖或發(fā)送日志過(guò)來(lái)。相對(duì)來(lái)說(shuō)對(duì)開(kāi)發(fā)者的工作成本較低 通過(guò)事件查看器可以進(jìn)行快速的分析,如看到軟件崩的日志,那就可以證明確實(shí)是軟件崩潰了。后續(xù)咱的調(diào)查方向就可以向著軟件崩掉的方向進(jìn)行 也有可能通過(guò)事件查看器直接看到非常有效的信息,直接就結(jié)束戰(zhàn)斗,定位到了問(wèn)題 舉個(gè)栗子 有一次我在調(diào)試一個(gè)軟件的時(shí)候,用戶反饋說(shuō)軟件無(wú)法啟動(dòng)。我讓用戶發(fā)送了事件查看器的日志過(guò)來(lái),通過(guò)日志可以看到如下內(nèi)容 錯(cuò)誤應(yīng)用程序名稱: lindexi.exe,版本: 5.1.12.63002,時(shí)間戳: 0xedd2d687錯(cuò)誤模塊名稱: MSVCR100.dll,版本: 10.0.40219.325,時(shí)間戳: 0x4df2be1e異常代碼: 0x40000015錯(cuò)誤偏移量: 0x0008d6fd錯(cuò)誤進(jìn)程 ID: 0x994錯(cuò)誤應(yīng)用程序啟動(dòng)時(shí)間: 0x01d50ac3bd970061錯(cuò)誤應(yīng)用程序路徑: C:\Program Files\lindexi\lindexi.exe錯(cuò)誤模塊路徑: C:\Program Files\PowerShadow\App\MSVCR100.dll報(bào)告 ID: a0c5c0b1-76b7-11e9-9d20-94c69123de40 細(xì)心的伙伴也許一眼就看出來(lái)問(wèn)題了,出現(xiàn)問(wèn)題的是 MSVCR100.dll 模塊,然而這個(gè)模塊路徑居然是在一個(gè)不認(rèn)識(shí)的,名為 PowerShadow 的軟件的目錄下。這時(shí)候就可以大概確定問(wèn)題了,這是被投毒了 試試用谷歌好幫手,搜搜這個(gè)軟件是什么軟件。剛好搜到了這篇博客: 影子系統(tǒng)讓 C++ 程序無(wú)法運(yùn)行 于是這就結(jié)束戰(zhàn)斗了,調(diào)查到了問(wèn)題的原因,軟件無(wú)法啟動(dòng)是因?yàn)楸煌抖玖?,被影子系統(tǒng)投毒了。解決方法就是請(qǐng)用戶卸載影子系統(tǒng),因?yàn)橛白酉到y(tǒng)也不維護(hù)了,咱軟件層沒(méi)啥好掙扎的 可惜的是在很多用戶的設(shè)備上,事件查看器日常不工作。沒(méi)關(guān)系,能從事件查看器找到額外信息,就是賺到了 如果事件查看器找不到或不能用?咱還有其他很多工具可以用 尋找痕跡的時(shí)候,另一個(gè)常用的好工具就是任務(wù)管理器。任務(wù)管理器是 Windows 自帶的一個(gè)工具,可以幫助我們了解到非常多的信息 通過(guò)任務(wù)管理器尋找痕跡時(shí),可以按照如上圖所示的決策樹(shù)了解一下情況。如果不能在任務(wù)管理器里面看到進(jìn)程,那很可能就是進(jìn)程已經(jīng)崩掉了。如果能夠看到進(jìn)程,那可能就是進(jìn)程卡了。此時(shí)關(guān)注點(diǎn)可以是 CPU 使用率。如果 CPU 使用率不動(dòng),那可以猜猜可能是死鎖問(wèn)題,如果 CPU 使用率爆高,那可能是死循環(huán)等問(wèn)題。同步也看一下內(nèi)存使用率,雖然在任務(wù)管理器里面看內(nèi)存使用率不能真實(shí)反映內(nèi)存使用情況,但是可以作為一個(gè)參考。詳細(xì)關(guān)于如何正確查看程序的內(nèi)存使用情況,后面會(huì)有專門(mén)的內(nèi)容介紹 無(wú)論是何種情況,都可以試試撈一個(gè) DUMP 回來(lái)調(diào)試看看。當(dāng)然了,對(duì)于軟件崩掉的情況,先嘗試一下是不是能啟動(dòng)起來(lái),拼手的速度快速撈一個(gè) DUMP 回來(lái),如果不能,那后文還會(huì)和大家介紹其他工具來(lái)輔助撈 DUMP 文件 先回顧一下,咱的調(diào)查思路一開(kāi)始就是嘗試尋找痕跡。尋找痕跡的時(shí)候借助 Windows 里面提供的好用的工具,這里重點(diǎn)介紹的是事件查看器和任務(wù)管理器。通過(guò)事件查看器可以快速的了解到軟件崩潰的原因,通過(guò)任務(wù)管理器可以了解到軟件的運(yùn)行情況 在通過(guò)自帶的工具沒(méi)有明確收獲的情況下,則嘗試撈一個(gè) DUMP 回來(lái)開(kāi)發(fā)機(jī)器上進(jìn)行進(jìn)一步分析 本課程這里提到的 DUMP 文件是指 Windows 下的內(nèi)存轉(zhuǎn)儲(chǔ)文件,是一個(gè)二進(jìn)制文件,簡(jiǎn)單用人話說(shuō)就是將進(jìn)程的內(nèi)存內(nèi)容保存到文件里面。通過(guò) DUMP 文件可以有效還原出此時(shí)的進(jìn)程的內(nèi)存狀態(tài)和內(nèi)存里面的內(nèi)容,可以用于進(jìn)一步的分析。當(dāng)用戶環(huán)境里面沒(méi)有帶開(kāi)發(fā)工具時(shí),撈一個(gè) DUMP 文件回來(lái),可以幫助我們?cè)陂_(kāi)發(fā)機(jī)器上進(jìn)行進(jìn)一步的分析。撈 DUMP 分析的過(guò)程,相當(dāng)于給進(jìn)程做了一個(gè)快照,然后將其放在開(kāi)發(fā)機(jī)器上進(jìn)行進(jìn)一步的分析 假設(shè)進(jìn)程還在的話,那最簡(jiǎn)單的撈 DUMP 方式就是通過(guò)任務(wù)管理器右鍵選擇創(chuàng)建內(nèi)存轉(zhuǎn)儲(chǔ)文件了。對(duì)應(yīng)的英文系統(tǒng)是 Create memory dump file 菜單項(xiàng) 這里需要額外說(shuō)明的是,如果當(dāng)前系統(tǒng)是 x64 系統(tǒng),但是自己的進(jìn)程是 x86 進(jìn)程,那此時(shí)不建議使用默認(rèn)打開(kāi)的任務(wù)管理器撈 DUMP 文件。因?yàn)槟J(rèn)打開(kāi)的任務(wù)管理器是 x64 的,打出來(lái)的是 x64 轉(zhuǎn)儲(chǔ)文件,包含 WoW64 子系統(tǒng)的信息。詳細(xì)請(qǐng)看 你生成的轉(zhuǎn)儲(chǔ)文件有問(wèn)題嗎? - 知乎 正確的做法應(yīng)該是使用 現(xiàn)在假定撈到了 DUMP 文件了,那接下來(lái)的步驟就是如何分析 DUMP 文件了。當(dāng)然了,前置步驟就是如何將 DUMP 文件傳回到自己的開(kāi)發(fā)機(jī)器上,這里有一個(gè)小妙招就是將這個(gè) DUMP 壓縮一下。由于 DUMP 文件是內(nèi)存轉(zhuǎn)儲(chǔ)文件,大部分都是全零的內(nèi)容,壓縮率非常高。如果需要通過(guò)網(wǎng)絡(luò)等方式傳輸,那壓縮一下再傳輸會(huì)快很多 分析 DUMP 的工具有很多,我著重要和大家介紹的是太陽(yáng)系最強(qiáng) IDE —— VisualStudio。VisualStudio 已經(jīng)是一個(gè)成熟的 IDE 了,只需將 DUMP 拖進(jìn)去就可以了,聰明的 VisualStudio 可以自動(dòng)幫咱進(jìn)行分析 一般而言,將 DUMP 拖入到 Visual Studio 里面,接著點(diǎn)擊混合調(diào)試按鈕即可?;旌险{(diào)試是使用 托管 調(diào)試和 本機(jī) 調(diào)試的組合。托管調(diào)試是指調(diào)試 .NET 程序,本機(jī)調(diào)試是指調(diào)試其他非 .NET 系的程序?;旌险{(diào)試是指同時(shí)調(diào)試托管和本機(jī)代碼,因?yàn)橐话愣?.NET 系的應(yīng)用要在托管層崩潰是有點(diǎn)難度的,除非開(kāi)發(fā)者自己比較缺乏處理。然而本機(jī)代碼,如某些使用 C 、匯編、C++ 編寫(xiě)的程序,那就容易崩潰了?;旌险{(diào)試可以同時(shí)調(diào)試這兩種代碼。即使進(jìn)程完全不是 .NET 程序,也可以使用混合調(diào)試來(lái)調(diào)試 進(jìn)入混合調(diào)試之后,需要等待 Visual Studio 自動(dòng)分析。如果是第一次調(diào)試 DUMP 文件的,可能會(huì)在下載符號(hào)這一步卡住一會(huì)。大家可以出去喝個(gè)茶,等待一下,再回來(lái)看看。實(shí)在等不急了,那就點(diǎn)擊取消符號(hào)加載再繼續(xù)吧 好的,現(xiàn)在咱的進(jìn)度就是在用戶側(cè)發(fā)現(xiàn)了問(wèn)題,且不能通過(guò)事件查看器等結(jié)束戰(zhàn)斗。將用戶的 DUMP 文件撈回來(lái),通過(guò) Visual Studio 進(jìn)行分析。分析的方法就是將 DUMP 文件拖入 Visual Studio 里面,然后點(diǎn)擊混合調(diào)試按鈕。等待 Visual Studio 自動(dòng)分析,即可看到分析結(jié)果 那聰明的 Visual Studio 會(huì)幫咱分析出什么內(nèi)容呢?如何看 Visual Studio 的分析結(jié)果呢?常見(jiàn)的套路就是關(guān)注 Visual Studio 以下三個(gè)方面內(nèi)容
先來(lái)和大家介紹一下調(diào)用堆棧。調(diào)用堆棧是個(gè)好東西,調(diào)用堆棧是一個(gè)非常重要的內(nèi)容,可以幫助我們了解到程序是如何運(yùn)行的。通過(guò)調(diào)用堆棧可以看到程序是如何運(yùn)行的,是從哪個(gè)函數(shù)開(kāi)始的,是如何調(diào)用的,是如何返回的。默認(rèn)的 Visual Studio 調(diào)試布局里面,可以快速看到調(diào)用堆棧窗格 調(diào)用堆??梢匀绾慰??調(diào)用堆??梢院椭霸谟脩舳巳蝿?wù)管理器所見(jiàn)內(nèi)容進(jìn)行一起分析。如在任務(wù)管理器看不見(jiàn)進(jìn)程,即對(duì)應(yīng)進(jìn)程崩了的問(wèn)題,可以通過(guò)調(diào)用堆棧嘗試看到是誰(shuí)帶崩的,崩之前調(diào)用的是哪個(gè)函數(shù)。如果是在任務(wù)管理器能看到進(jìn)程,但是 CPU 使用率不動(dòng),那可能是死鎖問(wèn)題,可以通過(guò)調(diào)用堆棧看到是哪個(gè)函數(shù)卡住了主線程或進(jìn)入鎖。如果是 CPU 使用率爆高,那可能是死循環(huán)問(wèn)題,可以通過(guò)調(diào)用堆??吹绞悄膫€(gè)函數(shù)跑滿了線程 舉個(gè)真實(shí)的例子,以下就是我從用戶端撈回來(lái)的一個(gè) DUMP 文件。通過(guò) Visual Studio 分析,崩潰之前的調(diào)用堆棧如下 > 00000000() Unknown [Frames below may be incorrect and/or missing] Unknown nvumdshim.dll!710d0745() Unknown nvd3dum.dll!5989f2e1() Unknown nvd3dum.dll!595f1716() Unknown nvd3dum.dll!596b7827() Unknown nvd3dum.dll!598a6233() Unknown nvd3dum.dll!5989b95c() Unknown nvd3dum.dll!5989c33b() Unknown nvd3dum.dll!598816bc() Unknown nvumdshim.dll!710ca40e() Unknown nvumdshim.dll!710cbb78() Unknown nvumdshim.dll!710ca17f() Unknown nvumdshim.dll!710ca0d3() Unknown d3d9.dll!5ab86f81() Unknown ntdll.dll!_NtWaitForMultipleObjects@20 () Unknown KERNELBASE.dll!76f69723() Unknown 通過(guò)調(diào)用堆??梢钥吹绞?nvumdshim.dll 模塊帶崩的。這個(gè)模塊是 NVIDIA 顯卡驅(qū)動(dòng)的模塊。通過(guò)這個(gè)調(diào)用堆??梢钥吹绞?NVIDIA 顯卡驅(qū)動(dòng)帶崩的。這個(gè)問(wèn)題的解決方法就是更新 NVIDIA 顯卡驅(qū)動(dòng)。此問(wèn)題詳細(xì)請(qǐng)看 記因?yàn)?NVIDIA 顯驅(qū)錯(cuò)誤而讓 WPF 應(yīng)用啟動(dòng)閃退問(wèn)題 驅(qū)動(dòng)問(wèn)題是客戶端崩的常見(jiàn)問(wèn)題,表現(xiàn)就是在很多用戶電腦工作好好的,在某些用戶就起不來(lái) 修復(fù) DirectX 時(shí),我常用的就是 DirectX 修復(fù)工具,此工具下載地址是: https://blog.csdn.net/VBcom/article/details/6962388 講完了誰(shuí)帶崩的問(wèn)題,接下來(lái)再看另一個(gè)案例。對(duì)應(yīng) CPU 不動(dòng)的問(wèn)題,如下圖所示的調(diào)用堆棧 大家猜猜上面堆棧告訴咱什么問(wèn)題 通過(guò)以上的堆??梢灾肋M(jìn)入了鎖。此時(shí)的常見(jiàn)套路就是從上到下找找,找第一個(gè)咱自己程序集的調(diào)用函數(shù),如這里就找到了是在 lindexi.dll 里面的方法??梢灾赖氖沁@個(gè)方法有邏輯在等待鎖,且這個(gè)鎖就不返回。此時(shí)配合代碼食用更佳。咱這里能夠知道進(jìn)程卡住的原因是因?yàn)榈却i,且這個(gè)鎖不返回,而至于這個(gè)鎖在業(yè)務(wù)上是什么作用就需要咱進(jìn)一步配合代碼進(jìn)行分析了 再來(lái)看看對(duì)應(yīng) CPU 爆高的一個(gè)案例,此時(shí)堆棧里面的信息可以告訴咱,現(xiàn)在正在跑的方法是哪些。有可能就是當(dāng)前的調(diào)用堆棧的頂部的幾個(gè)方法有邏輯跑滿了線程了。同樣,此時(shí)配合代碼食用更佳 但有可能此時(shí)面對(duì)的情況是沒(méi)有代碼。如使用的是第三方庫(kù)等,此時(shí)靠堆棧信息是不夠的。先讓大家思考這個(gè)問(wèn)題,如果此時(shí)沒(méi)有代碼還可以如何進(jìn)一步分析?我將在后文和大家介紹如何通過(guò)三板斧來(lái)進(jìn)一步分析 回顧一下,這就是咱拖入 DUMP 文件之后,依靠 Visual Studio 里面的調(diào)用堆棧進(jìn)行問(wèn)題分析的常見(jiàn)三個(gè)案例。對(duì)應(yīng)軟件崩潰的問(wèn)題,可以通過(guò)調(diào)用堆??吹绞钦l(shuí)帶崩的。對(duì)應(yīng) CPU 不動(dòng)的問(wèn)題,可以通過(guò)調(diào)用堆??吹绞钦l(shuí)卡住了主線程。對(duì)應(yīng) CPU 爆高的問(wèn)題,可以通過(guò)調(diào)用堆??吹绞钦l(shuí)跑滿了線程 但是僅靠調(diào)用堆??赡苓€是不夠的,有時(shí)候需要更多的信息。接下來(lái)我將和大家介紹如何通過(guò)“三板斧”來(lái)進(jìn)一步分析 這里介紹的“三板斧”分別是寄存器、反匯編、內(nèi)存這三個(gè)方面的工具。通過(guò)這三個(gè)方面的工具可以幫助我們進(jìn)一步的分析問(wèn)題 需要說(shuō)明的是用到這三個(gè)工具時(shí)僅僅只是在咱有需要了解更多狀態(tài)信息的時(shí)候。而且通過(guò)這三個(gè)工具也不一定能夠準(zhǔn)確了解到問(wèn)題的原因。這三個(gè)工具的使用本身不難,但是其難點(diǎn)確是這幾個(gè)工具所見(jiàn)內(nèi)容的背后大家關(guān)于程序本身的理解以及軟件運(yùn)行機(jī)制的了解。如果對(duì)于軟件運(yùn)行機(jī)制不了解,那這三個(gè)工具所見(jiàn)內(nèi)容可能會(huì)讓人難以理解,或者是調(diào)查方向跑偏 依然使用剛才的例子,當(dāng)看到 CPU 爆高的時(shí)候,通過(guò)調(diào)用堆??梢钥吹绞悄膫€(gè)方法跑滿了線程。但是這個(gè)方法邏輯跑滿了,其原因是什么呢?調(diào)用堆棧可無(wú)法回答此問(wèn)題 試試先在 Visual Studio 里面打開(kāi)內(nèi)存、寄存器、反匯編窗格。這三個(gè)工具可以幫助我們進(jìn)一步分析問(wèn)題 打開(kāi)之后的 Visual Studio 的界面布局大概如上圖所示 拿本課程的 CPU 爆高的例子,先通過(guò)反匯編發(fā)現(xiàn)了可能存在的問(wèn)題,如想看看 rcx 寄存器里面存放了什么。通過(guò)寄存器窗格可以看到 rcx 寄存器里面存放了什么內(nèi)容。通過(guò)內(nèi)存窗格可以看到這個(gè)地址里面存放了什么內(nèi)容。剛好就看到了對(duì)應(yīng)的內(nèi)存里面存放了一段逗比代碼 使用 “三板斧” 本身的難度不大,但是其難點(diǎn)在于其背后的知識(shí)。如匯編知識(shí),寄存器的機(jī)制,以及軟件本身的運(yùn)行機(jī)制。這部分知識(shí)遠(yuǎn)遠(yuǎn)超過(guò)了本課程能介紹的范圍,需要大家自行學(xué)習(xí),但由于這部分知識(shí)的學(xué)習(xí)成本較高,所以在實(shí)際工作中,這部分知識(shí)可能并不是必須的。我只敢推薦大家在有余力的情況下進(jìn)行學(xué)習(xí),如果平時(shí)工作已經(jīng)很忙了學(xué)不過(guò)來(lái)了,那這部分知識(shí)還可以先放著。但是如果能夠掌握這部分知識(shí),那在調(diào)試問(wèn)題時(shí)會(huì)有所幫助 繼續(xù)和大家介紹 Visual Studio 的另一個(gè)調(diào)試工具——局部變量。局部變量也是個(gè)好東西,可以幫助我們了解到程序運(yùn)行時(shí)的狀態(tài)。通過(guò)局部變量可以看到程序運(yùn)行時(shí)的變量的值,可以幫助我們了解到程序運(yùn)行時(shí)的狀態(tài) 如看到了錯(cuò)誤之前的局部變量有一個(gè)名為 工具下載地址: https://learn.microsoft.com/en-us/windows/win32/debug/system-error-code-lookup-tool 如在這里咱可以看到的錯(cuò)誤信息是文件或文件夾名錯(cuò)誤,根據(jù)咱的業(yè)務(wù)邏輯,可能是文件名錯(cuò)誤導(dǎo)致的問(wèn)題。那接下來(lái)的調(diào)查方向就是看看為什么出現(xiàn)錯(cuò)誤的文件名了,這時(shí)候也許一看代碼就理解了 再舉另一個(gè)真實(shí)的例子,如看到的是如上圖的異常導(dǎo)致的崩潰。根據(jù)咱通過(guò)搜索引擎了解到的知識(shí),這個(gè) WindowsCodecs.dll 是 Windows 系統(tǒng)的 WIC 多媒體解碼層??赡艽藭r(shí)遇到的問(wèn)題和圖片等多媒體的編解碼有關(guān) 剛好在本例子里面,通過(guò)局部變量看到了出問(wèn)題的圖片的文件地址,此時(shí)的調(diào)查就更加有方向了。除了可能存在的 WIC 層的問(wèn)題外,還可以是圖片文件本身的問(wèn)題。如圖片文件投毒等問(wèn)題 延伸一下,如何了解圖片、音視頻等文件是否被投毒了?這里推薦一個(gè)工具,通過(guò) MediaInfo 工具可以幫助咱看到文件的許多信息 如這個(gè)文件就是一個(gè)假裝是 png 的 WebP 文件,然后投毒將 WIC 層搞崩了 MediaInfo 工具下載地址: https://mediaarea.net/en/MediaInfo/Download 好像… 還是有些問(wèn)題調(diào)試不出來(lái) 太陽(yáng)系最強(qiáng) IDE 也頂不住呀 那就試試上接近能調(diào)試一切的 WinDbg 吧 這個(gè)工具非常強(qiáng)大,只是有一個(gè)問(wèn)題。那就是有億點(diǎn)點(diǎn)上手門(mén)檻 在這里我告訴大家一個(gè)非常簡(jiǎn)單的方法,讓大家瞬間就能學(xué)會(huì)上手使用 WinDbg 工具調(diào)試問(wèn)題。方法就是請(qǐng)一個(gè)熟悉 WinDbg 的伙伴,讓他幫你調(diào)試,找到一個(gè)工具人幫你使用 WinDbg 調(diào)試問(wèn)題是最快能學(xué)會(huì)使用 WinDbg 的方法 回顧一下,以上咱就聊了在用戶端發(fā)現(xiàn)問(wèn)題,先嘗試使用 Windows 自帶工具快速進(jìn)行定位問(wèn)題。以及撈到 DUMP 文件之后,如何在開(kāi)發(fā)機(jī)器上通過(guò) Visual Studio 進(jìn)行進(jìn)一步分析。分析的方法就是將 DUMP 文件拖入 Visual Studio 里面,然后點(diǎn)擊混合調(diào)試按鈕。等待 Visual Studio 自動(dòng)分析,即可看到分析結(jié)果。分析的重點(diǎn)是調(diào)用堆棧、三板斧、局部變量。通過(guò)這三個(gè)方面的工具可以幫助我們進(jìn)一步的分析問(wèn)題 如果 Visual Studio 還不能解決問(wèn)題,那就找個(gè)工具人來(lái)幫忙使用 WinDbg 繼續(xù)調(diào)查問(wèn)題 這就是第一個(gè)大方向的內(nèi)容 第二個(gè)大方向就是事后現(xiàn)場(chǎng)的復(fù)現(xiàn)問(wèn)題。什么時(shí)候需要復(fù)現(xiàn)問(wèn)題?比如最簡(jiǎn)單來(lái)說(shuō)就是軟件啟動(dòng)即崩潰,完全來(lái)不及打開(kāi)任務(wù)管理器撈 DUMP 文件。這時(shí)候就需要復(fù)現(xiàn)問(wèn)題了,通過(guò)復(fù)現(xiàn)問(wèn)題可以幫助我們更好的定位問(wèn)題 復(fù)現(xiàn)問(wèn)題時(shí)也不是只是簡(jiǎn)單重復(fù)跑程序,而是可以通過(guò)更多的工具輔助來(lái)在復(fù)現(xiàn)問(wèn)題時(shí)更好的定位問(wèn)題 首要介紹的就是 ProcDump 工具 當(dāng)使用任務(wù)管理器撈不到 DUMP 或不好撈 DUMP 時(shí),使用 ProcDump 工具能夠更好的幫助我們撈 DUMP 文件。ProcDump 工具是 Sysinternals 的工具,下載地址是: https://learn.microsoft.com/zh-cn/sysinternals/downloads/procdump 為什么說(shuō)有時(shí)候不好使用任務(wù)管理器撈 DUMP 呢?因?yàn)楝F(xiàn)實(shí)往往很復(fù)雜。除了閃崩,軟件啟動(dòng)即崩潰導(dǎo)致的手速不夠快,撈不到 DUMP 文件之外,還有其他很多問(wèn)題。比如軟件就是處于似崩未崩的狀態(tài),期望抓到某個(gè)時(shí)機(jī)的狀態(tài),如軟件一定會(huì)在某次 CPU 爆高之后不能符合預(yù)期工作,然而 CPU 爆高的時(shí)間非常短,靠人類去看去抓是有些廢程序猿的。比如軟件半夜崩潰,只有在午夜12點(diǎn)才會(huì)崩潰,這時(shí)候人類可能已經(jīng)睡著了,即使沒(méi)睡著,可能錯(cuò)過(guò)了這個(gè)時(shí)間點(diǎn)就要等明天的午夜12點(diǎn)了。再比如是非必現(xiàn)的問(wèn)題,需要壓測(cè)才能復(fù)現(xiàn),期望自動(dòng)化收集,否則可能要跑幾千次才能復(fù)現(xiàn)一次,靠人類的工作量有些大 通過(guò) ProcDump 可以在程序萬(wàn)種死法中有效的生成 Dump 文件,只需使用好 ProcDump 的參數(shù)。具體參數(shù)作用可以參考 微軟官方文檔 和 如何在 NET 程序萬(wàn)種死法中有效的生成 Dump (上) - 一線碼農(nóng) - 博客園 這是一個(gè)小游戲,讓大家連連線,看看在什么情況下應(yīng)該使用什么方法 在調(diào)查思路這里,復(fù)現(xiàn)問(wèn)題時(shí)經(jīng)常伴隨使用 ProcDump 工具,因?yàn)?ProcDump 工具可以在非常多的情況下幫助我們撈 DUMP 文件 復(fù)現(xiàn)問(wèn)題時(shí),不僅只有 ProcDump 工具。還有可能面對(duì)的是事后現(xiàn)場(chǎng)的情況,此時(shí)需要使用更多的工具來(lái)輔助定位問(wèn)題。以及當(dāng)沒(méi)有調(diào)查思路時(shí),可以試試常見(jiàn)的問(wèn)題的探索幫助尋找思路 來(lái)和大家講講事后現(xiàn)場(chǎng)的調(diào)查 什么是事后現(xiàn)場(chǎng)?事后現(xiàn)場(chǎng)問(wèn)題在這里一般說(shuō)的是當(dāng)前的現(xiàn)場(chǎng)或能復(fù)現(xiàn)所抓取到的現(xiàn)場(chǎng)已經(jīng)不是問(wèn)題發(fā)生的現(xiàn)場(chǎng),而是發(fā)生問(wèn)題之后的現(xiàn)場(chǎng)了 比如找到問(wèn)題了,但問(wèn)題非本質(zhì)問(wèn)題。常見(jiàn)的就是通過(guò) DUMP 分析是如 空 異常的情況,導(dǎo)致崩潰的原因是因?yàn)榭罩羔槷惓?。但是空指針異常是如何產(chǎn)生的呢?這時(shí)候就需要通過(guò)事后現(xiàn)場(chǎng)分析思路調(diào)查來(lái)進(jìn)一步分析問(wèn)題 比如發(fā)生問(wèn)題的地方不是產(chǎn)生問(wèn)題的地方。如本課程的例子里面,崩潰原因是一張假裝 png 的 WebP 圖片,那這張圖片是哪里來(lái)的,為什么會(huì)使用這張圖片。如果此時(shí)代碼邏輯沒(méi)有幫助的話,那就需要進(jìn)一步通過(guò)復(fù)現(xiàn)問(wèn)題調(diào)查事前現(xiàn)場(chǎng)來(lái)進(jìn)一步分析問(wèn)題 比如系統(tǒng)性的問(wèn)題。常見(jiàn)的就是團(tuán)伙作案,不是單個(gè)應(yīng)用導(dǎo)致的問(wèn)題。這類問(wèn)題的難度在于其復(fù)雜度,可能難以抓到正確的現(xiàn)場(chǎng)。此時(shí)也需要通過(guò)多次復(fù)現(xiàn)問(wèn)題,抓取更多的信息,通過(guò)事前和事后現(xiàn)場(chǎng)的分析來(lái)進(jìn)一步分析問(wèn)題 面對(duì)事后現(xiàn)場(chǎng)和團(tuán)伙作案等問(wèn)題,采用微軟極品工具箱的 Process Monitor 工具,配合 DebugView 工具通常都能有不錯(cuò)的收獲 Process Monitor 工具下載地址: https://learn.microsoft.com/zh-cn/sysinternals/downloads/portmon Debugview++ 工具開(kāi)源地址: https://github.com/CobaltFusion/DebugViewPP DebugView 工具下載地址: https://learn.microsoft.com/en-us/sysinternals/downloads/debugview 從界面和交互上,DebugView++ 比 DebugView 更好用一些 舉個(gè)真實(shí)栗子來(lái)和大家演示多個(gè)工具之間的配合使用來(lái)調(diào)用一個(gè)有趣且復(fù)雜的問(wèn)題 這個(gè)問(wèn)題的開(kāi)始是測(cè)試同學(xué)和我報(bào)告了觸摸失效問(wèn)題,后來(lái)經(jīng)過(guò)進(jìn)一步調(diào)查發(fā)現(xiàn)其實(shí)是 explorer 未響應(yīng)問(wèn)題,表現(xiàn)就是 explorer 迷之閃黑 這個(gè)問(wèn)題復(fù)雜之處在于 explorer 不是咱的,咱也不熟悉,也不知道是什么導(dǎo)致的。而且 explorer 太龐大了,撈到 DUMP 分析壓力過(guò)大,耗時(shí)耗力。需要使用更多的工具輔助進(jìn)一步分析問(wèn)題 此時(shí)通過(guò) Process Monitor 工具抓取 explorer 進(jìn)程信息,發(fā)現(xiàn)了如上圖的有趣的內(nèi)容。里面很受我關(guān)注的就是存在了進(jìn)程退出 通過(guò)網(wǎng)上四處搜發(fā)現(xiàn) explorer 是一個(gè)多進(jìn)程軟件,進(jìn)程的退出和迷之閃黑可能有所影響。既然進(jìn)程退出了,那就試試上 ProcDump 工具在進(jìn)程之前之后抓一個(gè) DUMP 文件回來(lái)分析 由于 explorer 十分龐大,且咱也不熟悉 explorer 的代碼,來(lái)回抓了幾次 DUMP 分析都沒(méi)有什么收獲。直到某次抓取到了一個(gè)有趣的 DUMP 文件,通過(guò)這個(gè) DUMP 文件發(fā)現(xiàn)了在進(jìn)程退出之前的調(diào)用堆棧里面包含了 Shell32 的一些調(diào)用 再根據(jù)前面的 Process Monitor 工具抓到的在進(jìn)程退出之前碰的是 Realtek Bluetooth 藍(lán)牙模塊,于是重心就在 Shell32 和藍(lán)牙一起組合上面 既然大概定位到這里,那就繼續(xù)上 ShellView 工具。通過(guò) ShellView 工具進(jìn)行大量的 Shell32 組件的禁用,我的做法大概就是看哪個(gè)不開(kāi)森就禁用哪個(gè),進(jìn)行二分法的禁用,最終發(fā)現(xiàn)了是 Realtek Bluetooth 藍(lán)牙模塊導(dǎo)致的問(wèn)題 二分法的禁用就是先一口氣禁用一半的組件,看看問(wèn)題是否解決。如果解決了,那就說(shuō)明問(wèn)題在這一半里面。如果沒(méi)有解決,那就說(shuō)明問(wèn)題在另一半里面。然后再在這一半里面繼續(xù)二分禁用,直到找到問(wèn)題所在 經(jīng)過(guò)以上的調(diào)查工具可以了解到是藍(lán)牙相關(guān)模塊的問(wèn)題,集中火力找到明確的調(diào)試方向,很快就找到是藍(lán)牙驅(qū)動(dòng)的問(wèn)題 詳細(xì)的調(diào)試內(nèi)容可比這里介紹的有趣的很,請(qǐng)看 記一次調(diào)試資源管理器未響應(yīng)經(jīng)驗(yàn) 博客園博客只做備份,博客發(fā)布就不再更新,如果想看最新博客,請(qǐng)?jiān)L問(wèn) https://blog.lindexi.com/ 如圖片看不見(jiàn),請(qǐng)?jiān)跒g覽器開(kāi)啟不安全http內(nèi)容兼容 本作品采用知識(shí)共享署名-非商業(yè)性使用-相同方式共享 4.0 國(guó)際許可協(xié)議進(jìn)行許可。歡迎轉(zhuǎn)載、使用、重新發(fā)布,但務(wù)必保留文章署名[林德熙](https://www.cnblogs.com/lindexi)(包含鏈接:https://www.cnblogs.com/lindexi ),不得用于商業(yè)目的,基于本文修改后的作品務(wù)必以相同的許可發(fā)布。如有任何疑問(wèn),請(qǐng)與我[聯(lián)系](mailto:lindexi_gd@163.com)。 該文章在 2024/9/20 9:13:18 編輯過(guò) |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |