はじめに
rr
を使ったデバックを実際に試してみる
前準備
$ cd <work directory>
$ git clone https://github.com/aRaikoFunakami/rr_test.git
$ cd rr_test/
$ gcc -g -O0 -pthread a.c
$ code . &
アプリの実行を記録
$ rr record ./a.out
rr: Saving execution to trace directory `/home/raiko/.local/share/rr/a.out-49'.
100/array[0] = 10
100/array[1] = 5
100/array[2] = 3
100/array[3] = 2
1回目の実行では不具合は発生しなかった
(タイミングによって発生する不具合のため1回目の実行でエラーが発生する場合もある)
rr record ./a.out
rr: Saving execution to trace directory `/home/raiko/.local/share/rr/a.out-50'.
100/array[0] = 10
100/array[1] = 5
Floating point exception
2回目の実行では Floating point exception
が発生
このようにタイミングイシューで問題が発生する不具合は再現が難しいのだが、今回はrr
で実行を記録しているので不具合を再生することができる。
不具合の再生
$ rr replay -s 50505 -k
vscode で rr
に接続して再生する
再生するとExceptionが37行目で発生していることがわかる
例外の発生は array[2]
の値が 0
であるため、0除算
を実行してしまっているため
デバッグ
どこで array[2]
の値が 0
に設定されたのかを確認していく
30行目にブレークポイントを設定
DEBUG CONSOLE
で -exec rc
(-exec reverse-continue
) で巻き戻す
30行目に戻るとarray[2]=30
であることが確認できる
別スレッドで実行される thread_func
でarray[2]
の内容が書き換えられていると目星がつく
20行目にブレークポイントを設定して Continue
20行目まで実行されたときr=2
であり、array[2]=0
が実行されることが確認できる
これでFloating point exception
の発生原因を特定した
まとめ
rr
でアプリの実行を記録しておくことで、タイミングイシューで発生する不具合を再生して再現できる。
不具合によっては再現するまでに何時間、何日もかかるものも存在するが、rr
で実行を記録しておくことで不具合を再現する時間を大幅に短縮可能である。
また、例外エラー
が発生した場所から巻き戻し実行
することで、不具合の原因となった場所の特定することも比較的容易となることが確認できた。
関連記事