什麼是 Core Dump#
在 Unix 系統上,當 native 應用程式 crash 時,可以產生一個 core dump 檔案,這是應用程式在 crash 瞬間的記憶體映像。透過分析 core dump,你可以在程式結束後進行事後除錯(postmortem debugging)。
啟用 Core Dump#
最關鍵的設定是 core dump 的大小限制,預設通常為 0(不產生):
$ ulimit -c # 查看目前限制
$ ulimit -c unlimited # 設為無限制要永久生效,將指令加入 .bash_profile 或 /etc/profile。
用 gdb 分析 Core Dump#
$ gdb program-image core-dump-file
(gdb) where # 查看 crash 位置
(gdb) frame n # 切換 stack frame
(gdb) info locals # 查看 local 變數
(gdb) print expr # 求值表達式Core dump 非常有用,你可能會想在程式遇到內部錯誤時主動產生它。在程式碼中呼叫
abort()即可。
Windows 上的 Dump 檔案#
Windows 程式預設不會產生 dump 檔案,需要在程式中呼叫 MiniDumpWriteDump 函式:
- 在遇到內部錯誤時呼叫它(類似
abort()) - 透過
SetUnhandledExceptionFilter註冊 exception handler,在未捕獲的 exception 發生時自動產生 dump - 產生的 dump 檔案可以在 Visual Studio 中開啟分析
強制產生 Dump#
對於還在執行但已停止回應的程式:
- Unix — 送 SIGABRT signal:
kill -ABRT process-id(或在終端機按Ctrl-\) - Windows — 在工作管理員中右鍵點選程序,選 Create Dump File
Managed 語言的限制#
使用 C#、Java、JavaScript、Perl、Python、Ruby 等 managed 語言時,postmortem debugging 的支援可能不完整、廠商特定、或根本不存在。原因包括:
- 底層技術更為抽象且複雜(如 JIT 編譯)
- 作業系統無法直接建立有意義的 memory dump
- 對 memory dump 的需求更高(如數千個 thread、JavaScript 的 pending events)
建立 Crash Report 系統#
對於已部署到客戶端的應用程式,可以建立系統化的 crash report 流程:
- 程式端 — 設定在 crash 時產生 memory dump 和 metadata(程式版本、環境資訊、log 檔案等)
- 傳送機制 — 用另一個外部程式檢查 exit status,透過 HTTP POST 傳送 dump 和 metadata
- 接收端 — 架設 HTTP server 接收並儲存 crash 資料
- 版本管理 — 為每個 release 版本打 tag,保存對應的執行檔和 debug symbol(PDB 檔案)
- 除錯 — 以正確版本的原始碼、執行檔和 dump 檔案啟動 debugger
也可以考慮使用現成的 crash report framework,如 PLCrashReporter(iOS/OS X)或 hosted 服務如 Crittercism、New Relic、Splunk MINT。
重點回顧#
- 透過取得和分析 core dump / memory dump 來除錯已 crash 或 hang 的程式
- 建立 crash report 系統,系統化地收集和分析客戶端的 crash 資料
- 注意 managed 語言的 postmortem debugging 支援可能受限