今日は、キャンプで習ったことを少し書きます。
gdb を使った C 言語のデバッグ方法です。
C 言語って、以外にデバッガ使わないで開発してる人も多いのでは?
キャンプでやった時のように、ただ gdb を使うだけじゃなくて、emacs との合わせ技で "おいしいデバッグ生活" と。
使いこなせれば、某 /Y\$ 社製 IDE のデバッガにも(ry
忘れてしまいそうなので、独自にメモっておくためにも。
なんか、このへんのことがテキストにもあんまり載ってなかったような気がしたので、参加者の方もおさらいがわりに利用してみてください。
Emacs 信者になりつつある僕が書いたものなので、emacs がある程度使えないと厳しいかもしれないけど。
Emacs があれば、なんでもできる!(何w
一応、超やさしく書いてみます。
[Emacs 初心者への注意書き]
- C-x と表記してある場合、Ctrl + x と押してあげてください。
- M-x と表記してある場合も、Esc + x な感じ。
1. まず、テスト用のソースを書こう。
emacs を立ち上げてください!
test.c など、適当な名前でファイルを開いて編集します。
emacs test.c &
こんな感じで、emacs を開いてあげると簡単かも。
まあ、サンプルなんて何でもいいんだけど、とりあえずこんな感じで。
#include <stdio.h>
int main(void)
{
int a, b;scanf("%d", &a);
b = a;
a++;
b--;
b = ++a;
b = a++;
printf("a=%d, b=%d\n", a, b);return 0;
}
入力し終わったら、C-x C-s で保存します。
2. コンパイルしてみよう。
ここで、まず作業の効率化のためにウィンドウを3つに分けましょう。
C-x 3 で横に分割。
C-x 2 で縦に分割できます~。
で、次に一つのウィンドウでターミナルを使えるようにします。
ここでは使いやすいように、左上のウィンドウを選択してください。 (ウィンドウの移動は C-x o)
そして "M-x ansi-term" と入力して、Enter を2回ぐらい押すとターミナルがでるはずで~す。
ここから、gcc のコンパイルなど、ターミナルで行う作業と同じことができます。
こういうところが、emacs の便利なところであったりします。
(ってなに、emacs 教叩きこんでるんだw)
ここで、先ほど保存した C のソースをコンパイルしてみます。
が、一つ注意が必要です。
通常は "gcc test.c" なんて感じでコンパイルすると思いますが、デバッガを使うときにはあるオプションが必要です。
ココ大変重要だったりします。
gcc -g test.c
としてあげてください。(こうすることで、デバッグ情報が付加されます。)
ま、あとは適当に ./a.out とか実行して、ちゃんと動くか確認してみてくださいね。
10 を入力すると、"a=13, b=12" とか帰ってくるはずです。
3. デバッグしてみる?
では、gdb を使って、実際に Emacs 上でデバッグしてみましょう。
M-x gdb と Enter してみてください。
たぶん、下の方に
Run gdb (like this): gdb
とか表示されてるんじゃないかと思う。
これ、バージョンによってっぽいんだけど、僕が使ってる Fedora 9 だと
Run gdb (like this): gdb --annotate=3 a.out
って、ここまで入力してくれちゃってた。
annotate はとりあえずここでは置いておいて、a.out というのはデバッグする実行ファイルなので、これを指定しないと動かない。
もし、gdb だけ表示されてる場合は、a.out (または実行ファイル名) を入力してあげてないと動かないと思う。
そこまで入力して、Enter してあげると、たぶん gdb の画面が表示されるのではないかと思う。(右下のウィンドウ)
じゃあ、まずは手慣らし、普通に実行してみよう。
(gdb) r
r または run と入力すると、実行が始まる。
このプログラムは、まずはじめに scanf してるので、なにか数字を入力してあげると、まだ何もしてないのでそのまま実行されて結果が表示されると思う。
とりあえず、最初はこんな感じ。
次に、ブレークポイントを設定してみますか。
ブレークポイントっていうのは、Visual $tudio ユーザーおなじみの、そこでプログラムを一時停止するフラグみたいな。
ブレークポイントの設定は、"b 行番号" または "break 行番号" のように設定します。
(gdb) b 8
Breakpoint 1 at 0x80483d8: file test.c, line 8.
このような感じです。
ブレークポイントを設定すると、右側のエディタ部分に、赤い丸印が表示されると思います。
(残念ながら、古い Emacs だとなにもひょうじされないんだお)
これは、その行にブレークポイントを設定しているという意味で、gdb 単体で使わずに Emacs とコンボで使う理由はこういうところにあります。
gdb 単体では、非常に使いづらいのではないかと思います。
ではここで、また run して実行してみましょう。
(gdb) run
Starting program: /home/hogehoge/a.out
10Breakpoint 1, main () at test.c:8
(gdb)
こんな感じで、実行が止まると思います。
この状態で、プログラムは終了したように見えますが、まだ一時停止してるだけで動いています。
例えば、ここで "p 変数名" または "print 変数名" などと入力してみましょう。
(gdb) p a
$1 = 10
(gdb) p b
$2 = 7566784
(gdb)
このように、変数名が表示されます。
ちなみに、これは 8 行目でストップしているのですが、a は scanf で入力された値を、b は初期化してないので適当な値が表示されてます。
一時停止中は、さまざまな作業をすることができるので、気になる所にブレークポイントを付けて、そこで変数の中身などを除いてデバッグという感じです。
これだけでも、プログラムの開発効率が printf デバッグに比べてかなり上がることでしょう。
そして、ブレークポイントを抜けてそのあとのプログラムを実行するには "c" を入力します。
(gdb) c
Continuing.
a=13, b=12Program exited normally.
(gdb)
その後にブレークポイントがない限り、最後までずっと実行されます。
Visual $tudio ユーザーおなじみの、ステップ実行はないのか?
もちろんあります。
ブレークポイントの後、一行ずつ実行を進めて様子をみたいときには "s" を入力します。
(gdb) r
Starting program: /home/hogehoge/a.out
10Breakpoint 1, main () at test.c:8
(gdb) p a
$3 = 10
(gdb) p b
$4 = 7566784
(gdb) s
(gdb) p a
$5 = 10
(gdb) p b
$6 = 10
(gdb)
このように、s を押すたび一行ずつ実行が進んでいきます。
また、一度 s を押すと、次からは空行で Enter しても、大丈夫だったりします。
そして、左側のエディタ部分を見てください。
黒い矢印のようなものが出現しているのがわかるでしょうか。
(こっちは、古い Emacs でもひょうじされるんだお)
これが、今実行している部分を指すポインタとなります。
最後に、ブレークポイントの削除について。
ブレークポイントの削除は、"clear 行番号" で行います。
(gdb) clear 8
Deleted breakpoint 1
こんな感じです。
そして、gdb の終了は "q" です。
ついでに、emacs の終了方法も書いておくと、C-x C-c で yes。
とりあず、こんな感じで、一通りの説明を終えようかと思いまず。
もしかしたら、少し進んだ応用編を書くかも?
では、おいしいツーハン生活 おいしいデバッグ生活をお楽しみくださいw
余談:
え?タイトルがおかしい?
このへんとは全く無関係なのでお構いなくw

コメントする