什麼是 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 流程:

  1. 程式端 — 設定在 crash 時產生 memory dump 和 metadata(程式版本、環境資訊、log 檔案等)
  2. 傳送機制 — 用另一個外部程式檢查 exit status,透過 HTTP POST 傳送 dump 和 metadata
  3. 接收端 — 架設 HTTP server 接收並儲存 crash 資料
  4. 版本管理 — 為每個 release 版本打 tag,保存對應的執行檔和 debug symbol(PDB 檔案)
  5. 除錯 — 以正確版本的原始碼、執行檔和 dump 檔案啟動 debugger

也可以考慮使用現成的 crash report framework,如 PLCrashReporter(iOS/OS X)或 hosted 服務如 CrittercismNew RelicSplunk MINT

重點回顧#

  • 透過取得和分析 core dump / memory dump 來除錯已 crash 或 hang 的程式
  • 建立 crash report 系統,系統化地收集和分析客戶端的 crash 資料
  • 注意 managed 語言的 postmortem debugging 支援可能受限