若想觀察特定變數的變化, watchpoint 比 breakpoint 易於使用。但 watchpoint 有個小問題, 一但離開 scope 後, gdb 會自動刪掉 watchpoint。
若該變數是 member field, 就無法持續追踪不同 method 怎麼讀取或寫入它的值。這篇提供一個小技巧, 取用目標變數的指標, 再觀察指標取值的變數, 藉此讓 gdb 認定它不是區域變數, 借用該文的例子如下:
(gdb) p &var1 $1 = (int *) 0x41523c0 (gdb) watch *(int *)0x41523c0 Hardware watchpoint 1: *(int *)0x41523c0
若真的是區域變數的話, 可用 commands 定義簡短的指令, 之後進入函式時, 自動加回 watchpoint, 借用該文提供的例子:
(gdb) break func (gdb) commands > watch var > continue > end
commands 看來很方便, 還有許多適合應用的情境, 像是追踪網路連線輸出關鍵資訊, 可避免手動操作太久造成 timeout。
2012-02-04 更新
gdb 7.4+ 支援 watch -l, 就不用自己取位置再設 watchpoint 解套。在 7.4 之前想用這功能, 可使用 Scott 寫的 gdb-watch-location.py。用法是
$ wget https://raw.github.com/scottt/scottt-gdb/master/gdb-watch-location.py $ gdb -x gdb-watch-location.py PROG
在 gdb 裡會新增幾個指令: watch-l、rwatch-l、awatch-l 對應到 watch -l、rwatch -l、awatch -l。
1. 例一中,用 "watch -l var1" 即可 (Stackoverflow 中路人的建議不見得是最好的)
回覆刪除2. 你 watchpoints 與 commands 都有在用的話,可考慮打開 gdb global history: $HOME/.gdbinit
set history save on
set history size 4096
set history filename /home/fcamel/.gdb_history
然後像 ipython 一樣,撈 history 寫成 gdb script.
原來有watch -l 的用法! 我都還傻傻的印出memory address
刪除查了一下發現是最新的 gdb 7.4 才有的功能, 所以....路人的建議還是實用啦
回覆刪除