C言語のデバッグ入門:gdbの基本的な使い方と実践例

C言語のデバッグ入門:gdbの基本的な使い方と実践例

PR Amazonのアソシエイトとして、ITナレッジライフは適格販売により収入を得ています。

記事の文字数:2,814

C言語プログラミングにおける必須ツール「gdb」の基本的な使い方を解説します。コンパイル時の注意点から、ブレークポイントの設定、ステップ実行などのデバッグ手法まで、実践的な例を用いて紹介します。

ITエンジニアにお勧めの本 ↗

おすすめ

エンジニアが知っておきたい思考の整理術 複雑な情報を【理解する】【伝える】テクニック

難易度
実用性
図解

思考の整理というテーマを、実務ですぐに使える具体的な「技術」として落とし込んだ一冊です。

ベストセラー

世界一流エンジニアの思考法

難易度
実用性
思考法

技術スキル以上に大切な「考え方」をアップデートできる。世界基準の効率的な仕事術が学べます。

文系社会人のためのIT資格の歩き方: 文系のあなたに最適な道をご提案します (YKcreate kiki)

難易度
実用性
キャリア度

ロードマップが非常に明確。キャリアプランを見据えた、無駄のない学習順序を提案してくれます。

エンジニアを説明上手にする本 相手に応じた技術情報や知識の伝え方

難易度
実用性
コミュ力

「伝える技術」もエンジニアの重要なスキル。相手の視点に立った、具体的な説明のコツが満載です。

技術広報入門 ー テックブログから始めるエンジニアカルチャーのつくり方

難易度
実用性
独自性

テックブログを入口にエンジニア組織の文化をどう設計し、育てていくかという実践論が学べます。

C言語でプログラムを書いていると、コンパイルは通るのに実行結果が想定と異なる、あるいは「セグメンテーション違反(Segmentation fault)」でプログラムがクラッシュしてしまうといった問題に直面することが多々あります。このようなプログラムの誤りや実行時エラーの原因を特定し、修正するために欠かせないのがデバッガです。

本記事では、C言語における代表的なデバッガである「gdb(GNU Debugger)」の基本的な使い方について解説します。gdbを活用すれば、プログラムの実行を任意の場所で一時停止させたり、変数の値を一行ずつ確認したりすることができ、バグの早期発見・解決に大きく役立ちます。

gdbとは?C言語開発に欠かせないデバッグツール

gdb(GNU Debugger)は、GNUプロジェクトによって開発された強力なデバッガで、C言語やC++を含む多くのプログラミング言語に対応しています。プログラムの内部動作を可視化し、バグの原因を突き止めるための様々な機能を提供しています。

LinuxLinux [リナックス / ライナックス]オープンソースのOSカーネルやUNIX系環境では標準的に利用されており、コマンドラインから操作するのが基本です。最初はとっつきにくいかもしれませんが、基本コマンドを覚えるだけで劇的にデバッグ効率が向上します。

gdbを使うための準備:C言語コードのコンパイル方法

gdbでC言語のプログラムをデバッグするには、コンパイル時にデバッグ情報を含める必要があります。これには、gccコンパイラの -g オプションを使用します。

Terminal window
gcc -g -O0 target.c -o target
  • -g:プログラムにデバッグ情報を追加し、gdbでソースコードと紐付けたデバッグを可能にします。(※ #define などのマクロ定義もデバッガ内で参照したい場合は、より詳細な情報を含む -g3 を指定すると便利です)
  • -O0(一般的に「オーゼロ」と読みます):コンパイラによる最適化を無効にします。最適化が有効だと、ソースコードの行と実際の実行処理が一致しなくなり、デバッグが困難になるため指定することをおすすめします。

gdbの基本的な使い方:起動と終了

gdbの起動方法

コンパイルして生成された実行ファイル(例:target)を引数にして、gdbコマンドを実行します。

Terminal window
gdb ./target

起動すると、(gdb) というプロンプトが表示され、コマンド入力待ち状態になります。

gdbの終了方法

gdbを終了するには、quit コマンド(または省略形の q)を入力します。

(gdb) quit

C言語デバッグでよく使うgdbの基本コマンド一覧

gdbには数多くのコマンドがありますが、日常的なデバッグで使うのは以下のコマンドが中心です。各コマンドには省略形が用意されており、入力の手間を省くことができます。

コマンド省略形説明
runrプログラムの実行を開始する
breakbブレークポイント(一時停止位置)を設定する
nextn次の行を1行実行する(関数の中には入らない)
steps次の行を1行実行する(関数の中に入る)
continuec次のブレークポイントまでプログラムの実行を再開する
printp変数や式の現在の値を表示する
listl現在実行中の周辺のソースコードを表示する
info locals-現在のスコープにあるローカル変数の一覧と値を表示する

info locals には公式な1文字の短縮形はありませんが、gdbはコマンドが一意に特定できる範囲での部分入力を受け付けるため、実用上は i lo が標準的な省略形として広く使われています。

実践チュートリアル:gdbを使ったC言語プログラムのデバッグ手法

ここでは、意図した通りの結果にならない単純なプログラムを例に、実際にgdbを使ってバグを見つける流れを体験してみましょう。

デバッグ用サンプルプログラム(C言語)

以下の calc.c は、1から5までの整数の合計(本来は15)を計算して表示するプログラムですが、変数の初期化に関する誤りを含んでいます。

calc.c
#include <stdio.h>
int main() {
int sum;
int i;
for (i = 1; i <= 5; i++) {
sum = sum + i;
}
printf("1から5の合計は: %d\n", sum);
return 0;
}

コンパイルして実行してみます。

Terminal window
gcc -g -O0 calc.c -o calc
./calc

環境によっては、実行結果が 15 にならず、デタラメな数値が表示されることがあります。この原因をgdbで探ります。

なお、このような単純な未初期化変数の問題は、gdbだけでなくコンパイラの警告によって発見できる場合もあります。開発時には -Wall -Wextra などの警告オプションも併用すると効果的です。

gdbを用いたバグ特定の手順

1. gdbを起動する

Terminal window
gdb ./calc

2. ブレークポイントを設定する

今回は sum = sum + i; が実行される直前の状態を確認したいので、関数内の特定の行(ここでは8行目)にブレークポイントを張ります。

(gdb) b 8
Breakpoint 1 at 0x...: file calc.c, line 8.

※ 実際の表示は環境によって異なります。 ※ b 8 のように、ソースファイルの行番号を指定してブレークポイントを設定することも可能です。

3. プログラムを実行する

(gdb) run
Starting program: /path/to/calc
Breakpoint 1, main () at calc.c:8
8 sum = sum + i;

ブレークポイントで実行が一時停止します。

4. 変数の値を確認する

この時点での変数 sumi の値を見てみましょう。

(gdb) p sum
$1 = <不定な値>
(gdb) p i
$2 = 1

<不定な値> は説明上の表記です。実際のGDBでは環境によって異なる数値などが表示される場合があります。

ここでバグの原因が判明します。i にはループの初期化によって 1 が入っていますが、このプログラムでは sum が初期化されていません。C言語では、初期化されていないローカル変数は「不定値」を持つため、その値を読み取って計算に使用すると動作は未定義になります。したがって環境によって異なる値が表示される場合があります。

sum が初期化されないまま計算に使用されていることが、今回のバグの原因であると分かります。このようにして、想定と実際の挙動のズレや変数の異常な状態を見つけるのがデバッグの基本です。

5. gdbを終了してコードを修正する

(gdb) quit

calc.c の変数宣言を int sum = 0; に修正して再コンパイル・実行すれば、正しい結果が得られます。

gdbのより高度な使い方(条件付きブレークポイント)

ループ処理の中で、特定の条件を満たした時だけプログラムを止めたい場合は、条件付きブレークポイントが便利です。

(gdb) break 8 if i == 4

これにより、指定した行(ここでは8行目)に到達したとき、i == 4 が成立する場合だけ停止します。ループ回数が多いプログラムのデバッグで非常に重宝します。

まとめ:gdbをマスターしてC言語のデバッグ効率を上げよう

C言語のプログラミングにおいて、gdbは強力な武器となります。最初はコマンド操作に慣れないかもしれませんが、 「-gをつけてコンパイル」「runで実行」「breakで止める」「printで値を確認」「next/stepで進める」 という基本サイクルを覚えるだけで、バグ解決のスピードは飛躍的に向上します。

printf関数を使って変数を出力する「printfデバッグ」も有効ですが、複雑なプログラムやセグメンテーション違反などの実行時エラーの原因究明にも、gdbは非常に役立ちます。ぜひ本記事を参考に、C言語開発でのgdb活用を始めてみてください。


以上で本記事の解説を終わります。
よいITライフを!
ITナレッジライフ 運営者
この記事を書いた人

Z (ITナレッジライフ)

現役のITエンジニア。Linux、プログラミング、IT用語など、日々の業務で得た「痒いところに手が届く」技術情報を発信しています。

プロフィールと編集ポリシーを見る

ITエンジニアにお勧めの本 ↗

おすすめ

エンジニアが知っておきたい思考の整理術 複雑な情報を【理解する】【伝える】テクニック

難易度
実用性
図解

思考の整理というテーマを、実務ですぐに使える具体的な「技術」として落とし込んだ一冊です。

人気記事


記事を評価

Thanks!
目次
Scroll to Top