什麼是 Reverse Debugging#

現代電腦豐富的 RAM 和快速的 CPU 使得反向執行程式成為可能。其原理是讓每條指令記錄它所做的變更,在反向執行時撤銷這些變更。

解決的痛點#

在傳統除錯中,當你到達某個執行點才發現 bug 已經發生了,你只能:

  1. 從頭重跑程式
  2. 在更早的地方設 breakpoint
  3. 期望這次能抓到問題
  4. 一個不小心 step over 就又錯過了

有了 reverse debugging,你只需要反向執行程式(再往前走)直到找到問題點。

支援 Reverse Debugging 的工具#

  • Visual Studio IntelliTrace
  • Rogue Wave TotalView ReplayEngine
  • Undo Software UndoDB
  • gdb — 獨立使用或透過 Eclipse CDT

使用 gdb 的實際操作#

以一個簡單的加總程式為例,gdb 的 reverse debugging 流程:

(gdb) break main
(gdb) run
# 程式停在 main 入口

(gdb) display i
(gdb) display sum
(gdb) break 10        # 在函式最後一行設 breakpoint
(gdb) record           # 關鍵:啟動執行記錄
(gdb) cont             # 繼續執行到結束

此時可以用 reverse 指令回溯:

(gdb) reverse-next     # 反向 step over
(gdb) reverse-step     # 反向 step into
(gdb) reverse-continue # 反向執行到前一個 breakpoint

每執行一次 reverse-next,程式就回退一步,變數值也隨之還原,讓你能觀察 bug 是從哪一步開始出現的。

限制#

Reverse debugging 有以下限制:

  • 效能大幅下降 — debugger 在背後做了大量記錄工作
  • 記憶體需求高 — 需要儲存每步的變更
  • 回溯距離有限 — gdb 預設限制 200,000 條指令
  • 副作用無法撤銷 — 已輸出到終端機的字元、已從資料庫刪除的資料不會復原
  • 異步事件難以重現 — signal、網路封包等難以在重播時精確複製

儘管有這些限制,reverse debugging 在某些場景下能為你省下數小時的痛苦重複工作。

重點回顧#

  • 熟悉你的 debugger 的 reverse debugging 功能,在需要時能派上用場
  • record 啟動記錄後,就能使用 reverse-nextreverse-stepreverse-continue 等指令
  • 注意其效能與功能限制,將它視為工具箱中的一項特殊武器