除錯與工具

條件中斷點(conditional breakpoint)

在一個會跑一百萬次的迴圈裡、某一行上設一個普通的中斷點,是很惱人的,尤其當臭蟲只在第 743,219 次迭代發生時。停一百萬次、按一百萬次「繼續」根本沒指望。條件中斷點解決了這件事:它是一個附帶一個是非判斷的普通中斷點,只有在那個判斷為真時才真的把程式停下來。其餘每一次程式都繼續飛掠過那一行,只在你在乎的那個時刻暫停。

具體來說,你設一個中斷點,並用你程式裡的變數寫一個條件給它。在 gdb 裡:「break process.c:88 if id == 743219」,或者先設中斷點、再附上「condition 1 errno != 0」。每次到達那一行時,除錯器會默默地計算那個運算式;若為假,程式就像什麼都沒發生一樣繼續,若為真,程式就停下來、把控制權交給你。代價是真實存在的,但通常值得:除錯器得在每一次經過時隱形地暫停、檢查條件,這比一個光禿禿的中斷點慢,但比你每次手動停下來快得多。

為何重要:條件中斷點讓你直接跳到有趣的情況——那一個壞掉的輸入、那一個 NULL 指標、那一次計數器出錯的迭代——而不必手動單步走過數千次健康的迭代。一個近親是忽略計數(「這個中斷點跳過 50 次,然後才停」),在你大致知道是第幾次失敗時很好用。當你能把壞狀態描述成一個簡單的運算式時就用它;如果你還無法描述它,對可疑資料設一個監看點、或單純單步執行,也許能先帶你到那裡。

在 gdb 裡: break handle_item if item == NULL 意思是「只在 item 是空指標的那次呼叫才停進 handle_item」。迴圈會全速跑過所有有效的項目,正好在那個壞掉的項目上凍住,於是呼叫堆疊追蹤直接指向那個傳了 NULL 進來的呼叫者。

只在 item == NULL 時停下來,略過每一次健康的迭代。

這個條件由除錯器在每一次命中時計算,所以放在熱迴圈裡的條件中斷點可能明顯拖慢執行;若太慢,監看點或重新安排這個判斷可能更快。要注意這個條件只能使用在那一行範圍內可見的名稱。

又称
condition on a breakpoint帶條件的中斷點