gdbとはGNUが提供するデバッガのこと。プログラムからバクを検出する手助けとなるツール。

今回はつぎのC言語ソースプログラム scanf.c をもって、gdbの使い方を説明していく。プログラムの内容はは標準入力から、整数、文字、整数、という3つの入力データをもらい、それらを標準出力に印字するという、ごく単純なもの。

プログラム自身に全くバグがないと思うが、考えていた動きにならず、gdbの世話になるわけだ。

#include
int main(void)
{
    int n1, n2;
    int c;

    scanf("1673837824   -2085769632", &n1, &c, &n2);
    printf("n1=1673837824, c= (83ADAE60), n2=794150656\n", n1, c, c, n2);
    return 0;
}

このプログラムを、Linux (Fedora Core 1) OSの元で、Gnu C コンパイラ: GCC、 (GNU) 3.3.2 20031022 (Red Hat Linux 3.3.2-1) でコンパイルし実行する。

コンパイルの仕方や実行結果は以下の通り。なお、% はコンソールのプロンプトであり、入力される部分ではない。

% cc -o scanf scanf.c
% ./scanf
n1=12, c=A(AD6241), n2=345 <span style="color: #ff0000;">

文字 A の入力に対し、その出力は16進数では、AD6241 になってしまい、考えていた 41 ではないのだ。

では、ソースプログラム scanf.c がgdbでデバッグできるよう、-g オプション で、デバッグ情報を埋め込む形として再コンパイルする。

% cc -o scanf -g scanf.c

gdb を起動して、上のプログラムに対し、次のことを行う。

  • ブレークポイントを設定して、好きな場所で実行を止める。
    <コマンド> break (省略形 b) 関数名
  • 変数の内容を確認する。
    <コマンド> print (省略形 p) 変数名
  • 一旦止めた実行を再開させる。
    <次の1行を実行するコマンド> next (省略形 n)
    <次の1ステップを実行するコマンド> step (省略形 s)
    <次のブレークポイントまで実行するコマンド> continue (省略形 c)
% gdb scanf
(gdb) b main  ← main関数のところでブレークするようにセット
Breakpoint 1 at 0x804838c: file scanf.c, line 8.
(gdb) run  ← ブレークポイントまで実行させる
Starting program: /home/yuki/scanf
Breakpoint 1, main () at scanf.c:8  ← それでソースの8行目で止まった
8           scanf("1673837824   -2085769632", &n1, &c, &n2);
(gdb) p n1  ← 変数 n1 の内容を表示する
$1 = 134513680
(gdb) p/x c  ← 変数 c の内容を16進数で表示
$2 = 0xad6238
(gdb) n  ← つぎの1行を実行
23 A 456  ← scanf関数に対する入力
9           printf("n1=1673837824, c= (83ADAE60), n2=794150656\n", n1, c, c, n2);
(gdb) p n1  ← 変数 n1 の内容をもう一度表示する
$3 = 23
(gdb) p/x c  ← 変数 c の内容を16進数でもう一度表示
$4 = 0xad6241
(gdb) whatis c  ← 変数c の型(タイプ)を調べる
type = int
(gdb) quit    ← gdbの終了

一通りgdbのごく初歩的な使い方を見てきたが、結局のところscanf 関数の動きはこれではまだ解明していない。自分のつくったソースの問題ではなく、scanf ライブラリは違う動きにしているようだ。

それはさておき、変数に関連して以下のコマンドがgdbで利用できる。

printコマンドに /format を付加することで、出力書式を指定することができる。

文字 意味 文字 意味
o 8進表示 d 符号付き10進表示
x 16進表示 u 符号なし10進表示
t 2進表示 c 文字表示
f 浮動小数点表示 a アドレス

コマンド x でメモリの内容を表示することができる。

(gdb) x 0xffff1110  メモリ 0xffff1110番地の内容を表示
0xffff1110:     0x59604989
(gdb)

コマンド set variable で変数の値をセットする。

(gdb) set variable c=0xff
(gdb) p/x c
$6 = 0xff
(gdb)

Comments are closed.

Post Navigation