首先讓我為大家科普“崩了”是什么樣子
01系統(tǒng)崩潰
系統(tǒng)的崩潰主要發(fā)生在:程序未能注意到有東西出錯(cuò)、并繼續(xù)運(yùn)行,直到出現(xiàn)更嚴(yán)重的情況。
例如試圖“除以零”,進(jìn)而導(dǎo)致程序被迫中止。
崩潰很可能在出現(xiàn)誘因后立刻發(fā)生,或等待很久后才發(fā)生。
也有可能是錯(cuò)誤信息導(dǎo)致的,但這類信息通常是由操作系統(tǒng)或應(yīng)用程序框架顯示,而非由程序代碼本身顯示。
下圖是一個(gè)典型的崩潰對(duì)話框:
(應(yīng)用 Sample.exe 崩潰后 windows 顯示的錯(cuò)誤信息)
這個(gè)錯(cuò)誤信息是由 Windows 錯(cuò)誤報(bào)告組件 WerFault.exe 顯示的。
為了確認(rèn)這一點(diǎn),可以將 Procexp 的十字準(zhǔn)星圖標(biāo)拖拽到錯(cuò)誤信息上,并查看擁有該窗口的進(jìn)程。
如下圖顯示了 Procexp 所展示的,故障的 Sample.exe 和 WerFault.exe 之間的關(guān)系。
本例中,Kernelbase.dll內(nèi)的默認(rèn)進(jìn)程中崩潰處理代碼使用 Sample.exe的PID作為一個(gè)命令行參數(shù)啟動(dòng)了 WerFault.exe(在Windows 8.1 中,崩潰處理代碼還可對(duì)崩潰的進(jìn)程創(chuàng)建不可執(zhí)行的快照)。
(崩潰對(duì)話框是由 WerFault.exe 進(jìn)程顯示的)
02崩潰觸發(fā)
大部分崩潰均由無法處理的進(jìn)程異常觸發(fā)如果程序執(zhí)行過程中遇到反常、不尋常,或非法的、無法由程序直接處理的情況,就會(huì)發(fā)生異常。
隨后將拋出有關(guān)具體狀況以及遇到該狀況的上下文信息,并將控制權(quán)轉(zhuǎn)交給上一層異常處理程序。
異常處理程序可以修復(fù)所遇到的狀況,并將控制權(quán)返回給出現(xiàn)異常的位置;或立刻返回給出現(xiàn)異常時(shí)包含的區(qū)塊;或由系統(tǒng)繼續(xù)搜索能處理異常的處理程序。
如果找不到任何處理程序,則無法處理的異常會(huì)導(dǎo)致程序退出。
03硬件異常和軟件異常
硬件異常:
CPU 檢測(cè)到當(dāng)前 CPU 指令違反某個(gè)規(guī)則而無法完成。
最常見的部分例子包括:
1. 除以零;
2. 在 CPU 未處于特權(quán)模式(即 Ring 0) 的情況下執(zhí)行特權(quán)指令;
3. 執(zhí)行未定義的 Opcode,如果 CPU 的指令指針設(shè)置為錯(cuò)誤的內(nèi)存地址就會(huì)發(fā)生這 種情況;
4. 訪問未提交的虛擬內(nèi)存;
5. 寫入只讀內(nèi)存;執(zhí)行被標(biāo)記為不可執(zhí)行(NX)的內(nèi)存;以及棧溢出。
軟件異常:
與之相對(duì)的,如果程序檢測(cè)到無法由自己直接處理的不尋常或錯(cuò)誤狀況,則此時(shí)會(huì)特意拋出軟件異常。
04定義專用的異常類
C++和C#等語言的標(biāo)準(zhǔn)庫定義和使用的類(Class)可以將不同類型異常的各種信息封裝在一起,還使得程序員可以為自己的應(yīng)用程序定義專用的異常類。
例如.NET RegistryKey 類包含有關(guān) Windows 注冊(cè)表的訪問操作,如果用戶無權(quán)執(zhí)行所請(qǐng)求的操縱,則將會(huì)拋出 SecurityException。
程序員有責(zé)任了解自己的程序何時(shí)會(huì)拋出異常,并編寫能妥善處理異常的代碼,確保自己的程序不會(huì)崩潰。
如果在拋出異常時(shí),進(jìn)程附加了 ProcDump 這樣的調(diào)試器,那么調(diào)試器將先于其他所有異常處理程序獲得通知。
這個(gè)通知也叫做第一輪異常(First-chance exception)。由于大部分第一輪異常最終都將由程序來處理,因此通常可忽略此類異常。
如果沒有異常處理程序可以處理這樣的異常,那么調(diào)試器會(huì)再次收到 第二輪異常(Second-chance exception)的通知,這類異常也叫做未處理的異常(Unhandled exception)。
05區(qū)別排查
第一輪和第二輪異常的區(qū)別對(duì)排錯(cuò)工作很重要。
例如應(yīng)用程序可能由于開發(fā)者未能提供相應(yīng)的異常處理 代碼導(dǎo)致在遇到未處理的異常后崩潰。
而附加的調(diào)試器可能根本沒機(jī)會(huì)看到第二輪異常,因?yàn)閼?yīng)用程序 構(gòu)建時(shí)所選擇的目標(biāo)平臺(tái)已經(jīng)在應(yīng)用的外圍提供了異常處理機(jī)制,在異常變?yōu)?ldquo;未處理”狀態(tài)并傳遞給 調(diào)試器之前就已接手了這個(gè)異常。
下圖 顯示了一個(gè).NET 窗體應(yīng)用由于未處理的異常而顯示的崩潰對(duì)話框。
該應(yīng)用程序的開發(fā)者并未提供異常處理程序,但.NET Framework 庫代碼提供了,并顯示了下圖 中 所示的對(duì)話框。
與之前的崩潰信息不同,這則錯(cuò)誤信息是由出現(xiàn)異常的進(jìn)程顯示的。
(NET Framework捕獲了一個(gè)窗體應(yīng)用中出現(xiàn)的未處理異常)
可以運(yùn)行 Procmon 直到錯(cuò)誤出現(xiàn),停止追蹤,篩選掉不相關(guān)的事件,然后在追蹤記錄中從后向前查看,找到能代表問題根源的信息。
如果崩潰發(fā)生在啟動(dòng)或登錄過程中,可能意味著某個(gè)自動(dòng)運(yùn)行的組件嫌疑最大。
此時(shí)可以使用 Autoruns 找出可能性最大的組件,并將其暫時(shí)或永久禁用;Autoruns 還可以幫我們找出需要更新的組件。
ProcDump 在崩潰故障排錯(cuò)中非常有用,該工具可在第一輪或第二輪異常時(shí),以及在被很多其他類型事件 觸發(fā)后捕獲用戶模式的轉(zhuǎn)儲(chǔ)。該工具還可將獲取的信息實(shí)時(shí)發(fā)送給 Procmon,這樣就可以將異常信息與發(fā) 生時(shí)的注冊(cè)表、文件、網(wǎng)絡(luò),以及進(jìn)程事件結(jié)合在一起查看。
有人戲稱,天天宅在家,想知道沙雕網(wǎng)友們最愛干的事是啥?
看熱搜就知道,愛它就要?dú)Я怂瑦壅l,誰就崩!
其實(shí)不全然,看看釘釘~
那么問題來了,釘釘憑什么在一眾平臺(tái)中脫穎而出、屹立不倒?
原來,釘釘背后的阿里云提前預(yù)防了由于人流過多而造成的崩。
假設(shè)群眾們是磨刀霍霍向平臺(tái)的服務(wù)器殺手,那么程序員們就是妙手回春的白衣天使~
衷心感謝各位程序員日以繼夜的辛苦碼作,讓我們?cè)诩依镆材軙诚砭W(wǎng)絡(luò)!
還想了解更多服務(wù)器的使用訣竅嗎?這本《Windows Sysinternals實(shí)戰(zhàn)指南》推薦給大家,本書匯集了微軟CTO多年實(shí)戰(zhàn)經(jīng)驗(yàn)的總結(jié),全面透徹剖析了Windows系統(tǒng)工具Sysinternals套件的使用方法以及難點(diǎn)、疑點(diǎn)。
無論是對(duì)廣大Windows系統(tǒng)管理員,還是普通用戶,如果掌握了本書中的技巧,就能事半功倍的解決日常電腦故障和出現(xiàn)的各種問題。






