『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)
続く。
コメント