本節書摘來自華章出版社《effective debugging:軟體和系統調試的66個有效方法》一書中的第1章,第1.6節,作[希]迪歐米迪斯·斯賓奈裡斯(diomidis spinellis),更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視
程式是一種很複雜的東西,是以它們通常都包含内置的調試機制。(至于怎樣給自己正在開發的軟體裡面添加這樣的機制,請參見第40條。)這種機制有很多好處,其中包括:
我們可以通過禁用背景執行或多線程執行等特性來簡化程式的調試工作。
我們可以有選擇地執行其中某一部分功能,以便通過測試用例來精确地再現相關的故障。
程式可以給我們提供與性能有關的報表及其他資訊。
程式可以把更多的資訊記錄在日志檔案中。
是以,我們應該花一些時間,看看自己要調試的這款軟體内置了哪些調試機制。想要了解這些機制,我們可以在程式文檔和源代碼裡面搜尋debug這個詞,這樣或許就能找到與開啟調試模式有關的指令行選項、配置檔案中的條目、建構選項、信号(适用于unix系統)、系統資料庫中的條目(适用于windows系統)或可以在指令行界面中執行的指令。
一般來說,開啟了調試選項之後,程式所輸出的資訊會更為詳細,于是,它的操作就會變得更加明确,有時甚至還會變得更加簡單。(但糟糕的是,開啟了這些選項之後,有些bug也會随之消失。)由于程式的日志檔案所記錄的資訊要比沒有開啟調試模式的時候更多,是以,我們可以通過這些内容來探究故障背後的原因(參見第56條)。下面舉幾個例子。
有些程式很容易就能通過一個指令選項來啟用其調試機制,啟用了之後,它在執行操作時就會給出更為詳細的資訊。例如,unix shell就提供了-x選項,用來詳細展示該shell所執行的指令。在調試一些比較微妙的文本替換問題時,這是很有用的。下面這段代碼是一個可以用shell來執行的循環:

把上述代碼放在腳本檔案裡,然後用開啟了指令追蹤機制的shell來執行它:
執行的時候,shell會産生下面這樣的資訊,這些資訊詳細展示了指令所輸出的内容以及替換之後的變量:
為了能夠更加順利地進行調試,我們在啟動程式的時候,通常可以把多個選項結合起來使用。例如,我們要排查ssh連接配接失敗的原因。假如修改全局的sshd配置檔案或鑰匙,那麼就可能會使其他人無法進行連接配接,是以,我們可以考慮用-f選項來啟動sshd,以便指定一份定制好的配置檔案,并且用-p選項來指定一個與預設端口不同的端口(請注意,用戶端連接配接伺服器時,也必須使用這個端口),此外,還要加上-d(調試)選項,使得程序運作在前台,并把調試消息顯示在終端視窗中。我們分别在伺服器端與用戶端采用下面這兩條指令來啟動服務并進行連接配接:
這些指令運作起來之後,會産生圖1.1這樣的調試資訊,其中的最後一條資訊揭示了連接配接失敗的原因。
調試機制也可以幫助我們排查性能方面的問題。例如,有下面這兩條sql查詢語句:
第一條語句不到10毫秒就可以完成,但是第二條語句卻用了3分鐘還沒有執行完。我們現在用sql的explain機制來解釋第二條語句耗時過長的原因(對于本例來說,這個原因當然是顯而易見的):
從圖1.2中的輸出資訊可以看到:由于第一條查詢語句使用了索引,是以隻需要掃描21個資料行就可以找出比對的結果,而第二條查詢語句沒有使用索引,是以必須把表格裡面的兩億兩千二百多萬個資料行全都掃描一遍,才能從中查出4個比對的結果。
還有一種調試機制,使得我們可以精确地定位到某一種情況。例如,某台主機正在忙碌地投遞上千條電子郵件消息,其中有一條消息無法投遞。我們要想知道無法投遞的原因,可以調用postfix的sendmail指令,同時以-v選項來開啟詳細輸出模式,并以-m選項來指定那條消息的辨別符。
執行上述指令之後,可以看到類似下方所示的輸出資訊。與剛才那個例子類似,在本例中,問題的原因也寫在最後一行。
要點
找出你正在調試的這款軟體所支援的調試機制,并以此來排查你所遇到的問題。