Allan Kelly
先懷疑自己的程式碼#
開發者——我們所有人——常常難以相信自己的程式碼有問題。「這太不可思議了,一定是編譯器壞了。」
然而,事實上,程式碼因為編譯器(compiler)、直譯器(interpreter)、作業系統(OS)、應用程式伺服器、資料庫、記憶體管理器或其他系統軟體的 bug 而出錯,是非常(非常)罕見的。是的,這些 bug 確實存在,但它們遠比我們想像的少得多。
個人經驗的教訓#
作者曾經遇過一次真正的編譯器 bug——優化掉了一個迴圈變數。但他有更多次以為是編譯器或作業系統的 bug,結果浪費了大量自己的時間、支援時間和管理時間,每次最後都發現其實是自己的錯。
先信任工具的品質#
假設你使用的工具是廣泛使用、成熟且被各種技術堆疊採用的,那麼幾乎沒有理由懷疑它們的品質。當然,如果工具是早期版本、全世界只有少數人使用、或是很少被下載的 0.1 版開源軟體,那就有理由懷疑。
鑑於編譯器 bug 極其罕見,你最好把時間和精力花在找出自己程式碼中的錯誤,而不是花在證明編譯器有問題上。
正確的除錯方法#
所有常見的除錯建議都適用:
- 隔離問題,用 stub 替換呼叫,用測試包圍它
- 檢查呼叫慣例(calling conventions)、共享函式庫(shared libraries)和版本號
- 向別人解釋問題
- 注意**堆疊損壞(stack corruption)**和變數型別不匹配
- 在不同機器上嘗試程式碼,以及不同的建置組態(如 debug 和 release)
質疑你的假設#
質疑你自己的假設,也質疑他人的假設。不同供應商的工具可能有不同的內建假設——同一供應商的不同工具也可能如此。
當別人回報了一個你無法重現的問題時,去看看他們在做什麼。他們可能在做你從未想過的事,或者以不同的順序操作。
不同類型的問題#
- 如果你有一個找不到原因的 bug,而你開始懷疑是編譯器,那就該檢查堆疊損壞了。尤其是當加入追蹤程式碼後問題會「移動」時更是如此。
- 多執行緒(multithreaded)問題是另一類讓人頭髮花白的 bug。所有建議都傾向使用簡單的程式碼。除錯和單元測試在多執行緒系統中的效果會大打折扣,設計的簡潔性至關重要。
在急著怪罪編譯器之前,記住 Sherlock Holmes 的建議:「當你排除了不可能的事物,剩下的無論多麼不可能,都一定是真相。」再搭配 Dirk Gently 的版本:「當你排除了不可能的事物,剩下的無論多麼不可能,都一定是真相。」