gdbを使って,サンプル
sample/c/sample1.cにおける
strtokの動作を確認してみよう.
次のように-gオプションをつけてgccでコンパイルすれば,gdb上でこのプログラムをデバッグすることができる.
% gcc -g -o sample1 sample1.c
% gdb sample1
... gdbのメッセージ ...
(gdb)
最後の(gdb)はコマンドを待つプロンプトである.
ここで,runコマンドを実行すると,通常通りプログラムの実行が開始され
る.プログラムにコマンドライン引数を渡す場合は,このrunに引数を与
えればよい.
(gdb) run
Starting program: .../sample1
foo, bar, hoge (foo, bar, hoge を入力)
1 = foo; 2nd = bar; 3 = hoge
[Inferior 1 (process XXXXX) exited normally]
次に,プログラム実行途中での変数の値を表示させて,strtokの動作を確
認してみよう.
プログラムを最初のstrtokの手前で一時停止させるために,ブレーク・ポ
イントを利用することができる.
と,breakコマンドによってブレーク・ポイントを9行目(a = strtok(...)の
行)に設定する.この状態でrunコマンドを実行し,入力文字列として,
上と同様にfoo, bar, hogeを与えると,strtokは実行されずに
Breakpoint 1, main () at sample1.c:9
9 a = strtok(in, " ,\n");
と表示されて,実行が一時停止される.このメッセージは,sample1.c
の9行目(の先頭)で停止していることを示している.ここで,printコマ
ンドを利用して,式in[0](つまり,文字列inの1文字目)を表示させ
ると,
(gdb) print in[0]
$1 = 102 'f'
in[0]の内容が正しく102(文字としてはf)になっていることが確認
できる.単にprint inとすると,
(gdb) print in
$2 = "foo, bar, hoge\n\000\005..."
と,終端文字より先も含めて,配列としてのinの値が全て表示される.こ
れによって,改行文字
\
nの次が終端文字'
\
000'になっていることがわかる.また,printfを利用して
フォーマットを指定して表示することもできるし,whatを利用して式の型
を確認することもできる.
(gdb) printf "%s\n",in
foo, bar, hoge
(gdb) what in
type = char [40]
ここでstepコマンドを実行すると,「次の命令のみ」を実行することがで
きる(ステップ・イン実行).
(gdb) step
10 b = strtok(NULL, " ,\n");
この時点でのaの内容と,inの内容を調べてみよう.
(gdb) printf "%s\n",a
foo
(gdb) print in
$3 = "foo\000 bar, hoge\n\000\005..."
aの内容が確かに最初のトークンfooになっていることがわかる.ま
た,もとの文字列in中の最初の区切り文字だった4文字目のカンマが終端文
字'
\
000'に置き換えられていることもわかる.同様に,
(gdb) step
11 c = strtok(NULL, " ,\n");
(gdb) printf "%s\n",b
bar
(gdb) print in
$4 = "foo\000 bar\000 hoge\n\000\005..."
と,2回目のstrtokによって,2つめのトークンbarがbに格納
され,barの後の区切り文字だったカンマが終端文字'
\
000'に置き換えられていることがわかる.
以上のように,strtok関数は,区切り文字を終端文字に置き換えながら,
返り値としてトークン文字列を返していることがわかる.
ブレーク・ポイント以降の実行を続
けるには,continueコマンドを実行する.
(gdb) continue
Continuing.
1st = foo; 2nd = bar; 3rd = hoge
[Inferior 1 (process XXXXX) exited normally]
ブレーク・ポイントは複数設定することが可能であり,この場合continue
コマンドによって「次のブレーク・ポイント」までが実行される.現在設定中の
ブレーク・ポイントは
で一覧表示できる.また,設定したブレーク・ポイントは,
などで削除できる.引数は行番号ではなく,ブレーク・ポイントの通し番号(info breakpointsで確認できる)であることに注意.
gdbを終了する場合は,quitコマンドを実行する.
NAKAZAWA Koji
2014-09-30