nanoを手探ってみる#2: デバッグ出力と操作画面の分離
前回はnanoのビルドが終わるところまでいきました。早速ソースコードで見つけた関数にブレイクポイントを設置して、gdbで処理を見てみます。ファイル読み込み機能に手を加えたいので、do_insertfile()という関数にブレイクポイントを張って実行します。
gdb ./nano <略> (gdb) b do_insertfile Breakpoint 1 at 0x40a6f7: file files.c, line 1064. (gdb) r
Ctrl+Rを押すとファイル読み込み機能が呼ばれて処理が止まるのですが…
nanoのUI、デバッグ用のログ、gdbのコマンドラインが混ざってすごいことになります。これでは出力が見づらくてデバッグがしにくいので、デバッグ出力と操作画面を分離させる方法を考えてみました。
gdb attachを使う
gdbにはattachという機能があり、この機能を使うと先に起動しておいたプログラムのプロセスに、あとからgdbの制御をかませることができます。使い方はgdbを起動してから
(gdb) attach [pid]
とするか、gdb起動時に-pオプションをつけて
gdb -p [pid]
とすればいいです。pidの値は
pgrep nano
とコマンドを打てば表示されます。attachの何が便利かというと、gdbをnanoとは別のターミナル画面で開くことができます。つまり、nanoのUIとgdbの制御画面を分離できるわけです。これだけだとまだnanoのUIとログ出力が混ざったままなので、nanoのstderr出力(デバッグのログはここから出ます)を適当なログファイルのリダイレクトします。さらにログファイルをtailすれば常にログを確認しながらデバッグができます。
まとめると、3つのターミナル画面を用意して1つめのターミナルでnanoを起動。このときstderr出力をlog.txtにリダイレクトする。
./nano 2> log.txt
2つめのターミナルでgdbをnanoにattachし、起動。(sudoがないとattachできません。)
sudo gdb -p $(pgrep nano)
3つめのターミナルでlog.txtをtail。
tail -f log.txt
ログが見やすくなって解析が捗ります。(16.04になってますが、見本用に撮っただけなので気にしないでください。)
ターミナルを複数起動するのが面倒という人にはtmuxなどのターミナルマルチプレクサもおすすめです。
#3に続きます。