経験豊富なコーダーに関係なく、開発するソフトウェアにバグが完全にないわけではありません。したがって、バグを特定して修正することは、ソフトウェア開発サイクルで最も重要なタスクの1つです。バグを特定する方法はたくさんありますが(テスト、コードの自己レビューなど)、問題がどこにあるかを正確に理解して簡単に修正できる専用のソフトウェア(デバッガーと呼ばれる)があります。
C / C ++プログラマーであるか、FortranおよびModula-2プログラミング言語を使用してソフトウェアを開発している場合は、バグやその他の問題についてコードを簡単にデバッグできる優れたデバッガー(GDBと呼ばれる)が存在することを知って喜ぶでしょう。この記事では、GDBが提供する便利な機能/オプションのいくつかを含め、GDBの基本について説明します。
ただし、先に進む前に、この記事に示されているすべての手順と例がUbuntu14.04LTSでテストされていることを言及する価値があります。チュートリアルで使用されているサンプルコードはC言語で書かれています。使用したコマンドラインシェルはbash(バージョン4.3.11)です。使用したGDBのバージョンは7.7.1です。
GDBデバッガーの基本
素人の言葉で言えば、GDBを使用すると、プログラムの実行中にプログラムの内部を確認できます。これにより、問題がどこにあるのかを正確に特定できます。次のセクションでは、実際の例を通じてGDBデバッガーの使用法について説明しますが、その前に、後で役立ついくつかの基本的なポイントについて説明します。
まず、GDBのようなデバッガーを正常に使用するには、コンパイラーがデバッガーに必要なデバッグ情報も生成するようにプログラムをコンパイルする必要があります。たとえば、このチュートリアルの後半でサンプルCプログラムをコンパイルするために使用するgccコンパイラの場合は、 -gを使用する必要があります。 コードのコンパイル中のコマンドラインオプション。
このコマンドラインオプションについてgccコンパイラのマニュアルページに記載されている内容を確認するには、こちらをご覧ください。
次のステップは、システムにGDBがインストールされていることを確認することです。そうでない場合で、UbuntuのようなDebianベースのシステムを使用している場合は、次のコマンドを使用してツールを簡単にインストールできます。
sudo apt-get install gdb
他のディストリビューションにインストールするには、ここに進んでください。
これで、デバッグ可能な方法でプログラムをコンパイルし、GDBがシステムにインストールされたら、次のコマンドを使用してプログラムをデバッグモードで実行できます。
gdb [prog-executable-name]
これによりGDBデバッガーが開始されますが、この時点ではプログラム実行可能ファイルは起動されません。これは、デバッグ関連の設定を定義できる時間です。たとえば、特定の行番号または関数でプログラムの実行を一時停止するようにGDBに指示するブレークポイントを定義できます。
次に、実際にプログラムを起動するには、次のgdbコマンドを実行する必要があります。
run
ここで言及する価値があるのは、プログラムにコマンドライン引数を渡す必要がある場合は、ここでそれらを指定できることです。例:
run [arguments]
GDBには、デバッグ時に役立つ多くの便利なコマンドが用意されています。それらのいくつかについては、次のセクションの例で説明します。
GDBの使用例
これで、GDBとその使用法についての基本的な考え方がわかりました。それでは、例を挙げて、そこに知識を適用しましょう。コード例は次のとおりです。
#include <stdio.h>
int main()
{
int out = 0, tot = 0, cnt = 0;
int val[] = {5, 54, 76, 91, 35, 27, 45, 15, 99, 0};
while(cnt < 10)
{
out = val[cnt];
tot = tot + 0xffffffff/out;
cnt++;
}
printf("\n Total = [%d]\n", tot);
return 0;
}
したがって、基本的に、このコードは、「val」配列に含まれる各値を選択し、それを「out」整数に割り当て、変数の前の値と「0xffffffff/」の結果を合計して「tot」を計算します。 」
ここでの問題は、コードを実行すると、次のエラーが発生することです。
$ ./gdb-test
Floating point exception (core dumped)
したがって、コードをデバッグするための最初のステップは、-gを使用してプログラムをコンパイルすることです。コマンドは次のとおりです:
gcc -g -Wall gdb-test.c -o gdb-test
次に、GDBを実行して、デバッグする実行可能ファイルを通知します。そのためのコマンドは次のとおりです。
gdb ./gdb-test
さて、私が得ているエラーは「浮動小数点の例外」です。ほとんどの人がすでに知っているかもしれませんが、xが0の場合、n%xが原因です。そのことを念頭に置いて、行番号にブレークポイントを設定します。 11、分割が行われています。これは次の方法で行われました:
(gdb) break 11
'(gdb)'はデバッガーのプロンプトであり、'break'コマンドを記述しただけであることに注意してください。
ここで、GDBにプログラムの実行を開始するように依頼しました:
run
したがって、ブレークポイントに初めてヒットしたとき、GDBが出力に表示したものは次のとおりです。
Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb)
上記の出力でわかるように、デバッガーはブレークポイントが設定された行を表示しました。それでは、「out」の現在の値を出力してみましょう。これは、次の方法で実行できます。
(gdb) print out
$1 = 5
(gdb)
ご覧のとおり、値「5」が出力されました。ですから、現時点では問題はありません。デバッガーに、次のブレークポイントまでプログラムの実行を継続するように依頼しました。これは、「c」コマンドを使用して実行できます。
c
'out'の値がゼロになるまで、この作業を続けました。
...
...
...
Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb) print out
$2 = 99
(gdb) c
Continuing.
Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb) print out
$3 = 0
(gdb)
さて、これが正確な問題であることを確認するために、今回は「c」の代わりにGDBの「s」(または「step」)コマンドを使用しました。理由は、プログラムの実行が現在一時停止している11行目を実行して、この時点でクラッシュが発生するかどうかを確認したかっただけです。
何が起こったのか:
(gdb) s
Program received signal SIGFPE, Arithmetic exception.
0x080484aa in main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
はい、上記の強調表示された出力で確認されたように、これは例外がスローされた場所です。最後の確認は、「s」コマンドをもう一度実行しようとしたときに行われました。
(gdb) s
Program terminated with signal SIGFPE, Arithmetic exception.
The program no longer exists.
したがって、このようにして、GDBを使用してプログラムをデバッグできます。
GDBはユーザーが探索して使用するための多くの機能を提供するため、ここで表面をかじったところです。 GDBのマニュアルページに目を通し、ツールの詳細を確認し、コードで何かをデバッグするときはいつでもそれを使用してみてください。デバッガーには少し学習曲線がありますが、一生懸命働く価値があります。