『ViVid Strike!』(ヴィヴィッド ストライク)
孤児の少女フーカは、数十人の不良を一人で相手できるほど喧嘩が強いのですが、トレーニングジムの選手の少女たちには、まったく敵わないのでした。
でも、さすが、自力で強くなっただけあります。センスがあるので、少しのアドバイスで、訓練している選手を打ち負かすことができたのでした。
いくら良いものを持ってても、地道に訓練している人には勝てませんね。地道っていうのが大事です。訓練も継続しなければ上達はやってきません。 継続するにはどうすれば良いでしょうか。目標や計画が必要といいますが、頭の硬い話だなあと思います。継続なんてものは習慣化するかどうかの問題でしょう。 目標や計画がなくても習慣化はできるはずです。「計画を立てるべき」と、もっともなことを言う人ほど、継続をしていないなあと思います(もちろんやってる人もいると思いますが)。と、過去の自分を批判してみました。継続させるには、「よーし、やるぞ」と自分に宣言するだけでいいんです。
さて、プログラミングができても、デバッグができない、なんてこともあるかと思います。デバッグテクニックも、地道に身につけていこうかと思います。
今回は条件breakです。いつものようにGDBを起動します。runコマンドの引数は”Vivid Strike !”としました。
takk@deb83:~/sysvbanner-1.0.15$ gdb banner
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
(省略)
(gdb) run Vivid Strike !
Starting program: /home/takk/sysvbanner-1.0.15/banner Vivid Strike !
Breakpoint 1, main (argc=4, argv=0xbffff774) at banner.c:132
132 for (argv++; --argc; argv++) {
(gdb)
スペース区切りで複数の文字列を指定すると、改行されてバナー表示されますが、”Strike”の文字列の時の動きを見たいので、*argvが”Strike”になった時にブレイクするように指定してみます。
ただ、C言語と同じで、文字列の一致ではなく、数値の一致になるので、**argv==’S’という形の条件設定となります。まずは、ソースを確認して、ブレイクする行を決めましょう。
(gdb) l
127 int main(int argc, char **argv)
128 {
129 int a, b, c, len, ind;
130 char line[80];
131
132 for (argv++; --argc; argv++) {
133 len = strlen(*argv);
134 if (len > 10)
135 len = 10;
136 for (a = 0; a < 7; a++) {
(gdb)
各文字列の処理の開始っぽい、133行目にブレイク設定します。
(gdb) b 133 if **argv=='S' Breakpoint 2 at 0x8048449: file banner.c, line 133. (gdb)
displayで、オート変数も自動表示するようにしておきます。
まとめられる変数は、括弧{}で、まとめます。
(gdb) disp {a,b,c,len,ind}
1: {a,b,c,len,ind} = {134514194, 134523828, 47, -1073743704, 134513341}
(gdb)
次に、変数lineも登録したいですが、80Byteの配列となっています。 このままでは以下のように全部表示されて見難くなります。
(gdb) p line $1 = "\001\000\000\000,\000\000\000\006\000\000\000}0\264,\000\000\000\000\024\3 67\377\277\210\366\377\277\200\366\377\277\062\202\004\b0\371\377\267\000\000\00 0\000\277\000\000\000\026o\352\267\377\377\377\377\256\366\377\277\370\333\341\2 67C\"\344\267\000\000\000\000}0\264,\001\000\000" (gdb)
ですので文字列にキャストして表示します。
(gdb) p/s (char*)line $2 = 0xbffff64c "\001" (gdb)
文字列にキャストすることで、0(NULL)が出現するところまでしか表示されません。
これをdisplayに登録しておきます。
(gdb) disp/s (char*)line 2: x/s (char*)line 0xbffff64c: "\001" (gdb)
現状の設定を確認しましょう。
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x08048440 in main at banner.c:132
breakpoint already hit 1 time
2 breakpoint keep y 0x08048449 in main at banner.c:133
stop only if **argv=='S'
(gdb) disp
2: x/s (char*)line 0xbffff64c: "\001"
1: {a,b,c,len,ind} = {134514194, 134523828, 47, -1073743704, 134513341}
(gdb)
では、実行(continue)してみます。
(gdb) c
Continuing.
# #
# # # # # # #####
# # # # # # # #
# # # # # # # #
# # # # # # # #
# # # # # # # #
# # ## # #####
Breakpoint 2, main (argc=2, argv=0xbffff77c) at banner.c:133
133 len = strlen(*argv);
2: x/s (char*)line 0xbffff64c: " # # ## # #####"
1: {a,b,c,len,ind} = {7, 37, 7, 5, 68}
(gdb)
Vividの結果表示がされましたが、 “Strike”でブレイクしたのでしょうか、*argvを確認してみます。
(gdb) p/s *argv $1 = 0xbffff8d2 "Strike" (gdb)
*argvが”Strike”になっていますね。
続いてステップ実行(next)していきます。
(gdb) n
134 if (len > 10)
2: x/s (char*)line 0xbffff64c: " # # ## # #####"
1: {a,b,c,len,ind} = {7, 37, 7, 6, 68}
(gdb)
lenが10を超えているかのif文ですが、dispのlenの値を見ると6ですので、超えませんね。
続いて、各for文をステップ実行します。
(gdb) n
136 for (a = 0; a < 7; a++) {
2: x/s (char*)line 0xbffff64c: " # # ## # #####"
1: {a,b,c,len,ind} = {7, 37, 7, 6, 68}
(gdb)
137 for (b = 0; b < len; b++) {
2: x/s (char*)line 0xbffff64c: " # # ## # #####"
1: {a,b,c,len,ind} = {0, 37, 7, 6, 68}
(gdb)
138 if ((ind = (*argv)[b] - ' ') < 0)
2: x/s (char*)line 0xbffff64c: " # # ## # #####"
1: {a,b,c,len,ind} = {0, 0, 7, 6, 68}
(gdb)
(*argv)[b]ということは、bが、文字列の先頭からの位置をしめしていますね。
bが文字列の長さつまり、len分回ります。
さらにステップ実行してみましょう。
(gdb) n
140 for (c = 0; c < 7; c++) {
2: x/s (char*)line 0xbffff64c: " # # ## # #####"
1: {a,b,c,len,ind} = {0, 0, 7, 6, 51}
(gdb)
141 line[b * 8 + c] = glyphs[(ind / 8 * 7) + a][(ind % 8 * 7) + c];
2: x/s (char*)line 0xbffff64c: " # # ## # #####"
1: {a,b,c,len,ind} = {0, 0, 0, 6, 51}
(gdb)
この行にbreakでブレイクポイントを設定して、continueで一周してみましょう。
(gdb) b
Breakpoint 3 at 0x80484ae: file banner.c, line 141.
(gdb) c
Continuing.
Breakpoint 3, main (argc=2, argv=0xbffff77c) at banner.c:141
141 line[b * 8 + c] = glyphs[(ind / 8 * 7) + a][(ind % 8 * 7) + c];
2: x/s (char*)line 0xbffff64c: " # # ## # #####"
1: {a,b,c,len,ind} = {0, 0, 1, 6, 51}
(gdb)
変数cが1になりました。回数を指定してcontinueしてみます。
(gdb) c 5
Will ignore next 4 crossings of breakpoint 3. Continuing.
Breakpoint 3, main (argc=2, argv=0xbffff77c) at banner.c:141
141 line[b * 8 + c] = glyphs[(ind / 8 * 7) + a][(ind % 8 * 7) + c];
2: x/s (char*)line 0xbffff64c: " ##### # ## # #####"
1: {a,b,c,len,ind} = {0, 0, 6, 6, 51}
(gdb)
5周回しました。次は変数cが7になるので、forから抜けますね。
(gdb) n
140 for (c = 0; c < 7; c++) {
2: x/s (char*)line 0xbffff64c: " ##### # ## # #####"
1: {a,b,c,len,ind} = {0, 0, 6, 6, 51}
(gdb)
143 line[b * 8 + 7] = ' ';
2: x/s (char*)line 0xbffff64c: " ##### # ## # #####"
1: {a,b,c,len,ind} = {0, 0, 7, 6, 51}
(gdb)
137 for (b = 0; b < len; b++) {
2: x/s (char*)line 0xbffff64c: " ##### # ## # #####"
1: {a,b,c,len,ind} = {0, 0, 7, 6, 51}
(gdb)
続く。


コメント