• 検索結果がありません。

C プログラムのデバッグ

第 7 章 言語処理系 ( コンパイラ ) 149

7.3 C プログラムのデバッグ

「プログラミング言語C(第2版)ANSI規格準拠」(共立出版)

test debug.cはtest.cの6行目〜8行目に#ifdef文を使ったプログラムを追加したもの です.”#ifdef (マクロ名)〜#endif”にはさまれた部分は,(マクロ名)が定義されている とコンパイルの対象になります.もし,マクロが定義されていない場合,この部分はコン パイル時に無視されます.つまり,コンパイル時にマクロを定義することで,デバッグ用 のプログラムを生成することができます.

マクロを定義する方法には,#defineをソースファイル中に定義する方法とコンパイル 時にコンパイラのオプションで指定する方法があります.このうち,コンパイル時にマク ロを指定するには,コンパイルオプションに”-D(マクロ名)”と指定します.

実行例 ³

$ gcc -o test debug test debug.c -DDEBUG

$ ./test debug Hello, C world!

This is debug.

$ gcc -o test debug test debug.c

$ ./test debug Hello, C world!

µ ´

7.3.3 デバッガの利用

printfを使ったデバッグの方法について説明しましたが,この方法では,デバッグした

い箇所に全部のデバッグ情報を書かなければなりません.また,短いプログラムの場合,

ソースコードを見ているだけでも簡単にバグを発見することができますが,ソースプログ ラムが長く,複雑になると,バグを見つけることが難しくなってきます.

そこで,デバッガというデバッグをサポートするツールを使います.一般的なデバッガ では,プログラムを途中で止めて変数の中身を見たり,1行ごとにプログラムを実行した りすることができます.これにより,非常に効率良くデバッグを行うことができます.例 えば,課題のプログラムなどでバグがどこにあるかわからなくなったら,デバッガを使っ てデバッグすることで,バグを見つけることができるかもしれません.

ここでは,次の簡単な剰余計算を行うプログラムをデバッグするとします.デバッガに は,gdb(GNUデバッガ)を使用します.

test gdb.c

³

1 #include <stdio.h>

2

3 int mymod(int i, int j) { 4 while(i >= j)

5 i -= j;

6 return i;

7 }

8

9 int main() {

10 int x = 20,y = 3;

11 printf("%d (mod %d) = %d\n",x,y,mymod(x,y));

12 return 0;

13 }

µ ´

デバッガを利用するためには,コンパイル時にデバッグに必要な情報をプログラムに埋 め込んでおく必要があります.そのためには,gcc”-g”オプションをつけてソースコー ドをコンパイルします.

実行例 ³

$ gcc -o test gdb test gdb.c -g

µ ´

このようにして実行ファイルを生成するとgdbを利用してデバッグを行うことができ ます.

次に,gdbコマンドを使って,gdbを起動させます.引数には,実行するファイルのファ イル名を指定します.

実行例 ³

$ gdb test gdb

µ ´

起動すると,以下のように表示されます.ここから,コマンドでデバッガを操作します.

gdbの起動

³

$ gdb test gdb

GNU gdb 6.3.50-20050815 (Apple version gdb-1346) (Fri Sep 18 20:40:51 UTC 2009)

Copyright 2004 Free Software Foundation, Inc.

(省略) (gdb)

µ ´

デバッガの使い方はいろいろとあるのですが,ここでは,プログラムを特定の場所で止 めるブレークポイントの機能を使って,途中でプログラムを止めてデバッグする方法を例 にして説明をしていきます.

ブレークポイントを設定するためには,breakコマンドを使います.breakコマンドの 引数には,関数名や行数を指定します.このとき,複数のファイルで構成されているプロ グラムにブレークポイントを設定するためには,ファイル名を指定する必要があります.

ファイル名を指定するには,”break (ソースファイル名):(関数名or行数)”というように,

引数にファイル名を含めて記述します.

実行例 ³

(gdb) break mymod

Breakpoint 1 at 0x100000e96: file test_gdb.c, line 4.

µ ´

ブレークポイントを設定したら,runコマンドを使ってプログラムを実行します.この とき,デバッグするプログラムに実行するための引数を付けたい場合は,runコマンドの 引数にその引数を入力します.

実行例 ³

(gdb) run

Starting program: /home/gikan/tebiki/tebiki01/compiler/test_gdb Breakpoint 1, mymod (i=20, j=3) at test_gdb.c:4

4 while(i >= j)

µ ´

実行したプログラムは,ブレークポイントを設定した場所に到達すると,その場所でプ ログラムが一時停止し,gdbでコマンドを入力できるようになります.

この状態で,変数の中身を見るためには,printコマンドを使用します.例えば,変数i の中身を表示するためには,以下のようにします.

実行例 ³ (gdb) print i

$1 = 20

µ ´

また,この状態で変数の中身を書き換えることもできます.その場合には,”(変数名)

= ()”と入力します.

一時停止している状態で1行処理を進ませたい場合には,nextコマンドを使います.こ れにより,1行ごとに処理を実行させていくことができます.また,nextなど,何度も同 じコマンドを入力しなければならないとき,毎回同じコマンドを入力するのは非常に面倒 です.そのため,gdbには前の操作をもう一度繰り返す機能がついています.これを行う ためには,何も入力されていない状態で¤£return¡¢を押します.

一時停止している状態では,さらに他の場所にブレークポイントを設定することができ ます.また,設定したブレークポイントを削除するためには,clearコマンドを使います.

clearコマンドの引数には,breakコマンドと同じようにして,削除するブレークポイント

の関数名や行数を指定します.

最後に,プログラムの実行を再開する場合には,continueコマンドを使用します.これ により,プログラムの実行を再開します.また,デバッガを終了するには,quitコマンド を使用します.

これ以外にも,条件付きのブレークポイントの設定やバックトレースの表示など,大変 便利な機能があります.詳細は,manコマンドやgdb起動中のhelpコマンド,インター ネット上の情報などを参考にしてください.