# デバッグ

## デバッグとは

デバッグするのは人間です。問題を解決するのは神です...

えーと、人間 という部分はこのセクションで紹介することです。そして 神 になれるかどうかは貴方次第です！

プログラムが思い通りに動かない時を想定してみると、そのプログラムにはバグまたは複数のバグが潜んでいると考えられます。これはコンパイル・エラーが原因ではありません - コンパイル・エラーは単純なエラーで先のバグと比較すると簡単に解決できます。その理由は、どこが問題であるかコンパイラが教えてくれるからです。言い換えると、バグ はプログラムを実行した時に発生するエラーで、解決するのは難しい (時には非常に難しい！) です。

バグがないと考えているプログラムは、必ずしも完璧にバグが無いわけではありません。我々が試行できることの全てがプログラムに潜むバグの数を減らします。バグを取り除く作業は デバッグ と呼ばれ、デバッグに使用するツールのことを デバッガ と言います。Anjuta はとてもユーザフレンドリでパワフルなデバッグ環境 (実際は、コマンドラインで使用するパワフルな GNU デバッガ gdb の GUI ラッパー版です) を提供します。

デバッガはプログラムの実行経過をたどって問題がありそうな部分を探しあてて、プログラムの実行を観察するために必要な情報をたくさん提供します。

### デバッグの対象

デバッグを始める前に、デバッグの対象 が何であるかを理解することが重要です。デバッグの対象はバグの実体に関係しており、プログラムを操作している最中に互いに影響を与えるものです。デバッグの対象には四つの種類があります:

1. 実行型式ファイル

2. シンボル・テーブル

3. コア・ファイル

4. プロセス

好きな時にこれらの対象のうち一つだけを有効にすることができます。デバッガを使う際に、これらの対象の全てを有効にする必要はありませんが、デバッグ作業を効率化するために、いくつか相互の連携が必要になってきます。例えば、[ 実行型式ファイル、シンボル・テーブル、プロセス ] という連携や [ 実行型式ファイル、シンボル・テーブル、コア・ファイル ] といった連携などです。

デバッグの対象のひとつである 実行型式ファイル は、デバッガを起動して実行型式ファイルを読み込むときに有効になります。

シンボル・テーブル は自動的に実行型式ファイルから読み込まれるので、各々操作する必要はありません。シンボル・テーブルは、プログラムのソース・コードに記述されたいろいろなシンボル (変数名や定数名など) をデバッガが識別するのに必要です。その情報はプログラムをコンパイルする際に追加されます (プログラムがデバッグ・オプション付きでコンパイルされた場合にのみ - 詳細は setting-compiler-options を参照下さい)。

コア・ファイル は、デバッガがコア・ファイルを読み込んだときに有効になります。コア・ファイルとはプログラムのメモリイメージで、通常は何か不正な処理が実行されたときにカーネルによってダンプされます。コア・ファイルは変数の内容、レジスタの値そしてエラーが発生した時点でのスタックのトレース情報を提供します。コア・ファイルを調査することで、プログラムのどの部分でおかしな処理を行ってコアがダンプしたかを見つけることが可能になります。

プロセス はデバッガ配下でプログラムが実行された時、または既に起動中のプロセスを追加した時に有効になります。

### デバッガの起動と停止

デバッガを起動する場合は、メニュー・アイテム デバッグ(_D)デバッガの起動 を選択して下さい。すると現在開発中のプロジェクトの実行型式ファイルを使ってデバッガが起動します。もしプロジェクトが開かれていない場合、現在編集しているファイルの実行型式ファイルを読み込みます。またプロジェクトが開かれておらず、さらに現在編集しているファイルもない場合、デバッガは起動しますが、実行型式ファイルは読み込みません。その場合は実行型式ファイルを手動で読み込んで下さい。

デバッガを起動したら、デバッグ・モードに移行します。デバッグが完了したら、メニュー・アイテム デバッグ(_D)デバッガの解放 を選択してデバッグ・モードを終了して下さい。

### 実行型式ファイルの読み込み

既にプロジェクトまたはファイルが開かれている場合、デバッガは自動的にその実行型式ファイルを読み込みます。別の実行型式ファイルを読み込む場合は、メニュー・アイテム デバッグ(_D)実行型式の読み込み(_X)… を選択して下さい。ファイル選択ダイアログが表示されます。デバッグする実行型式ファイルを選択して OK ボタンをクリックして下さい。

### プロセスに追加する

起動中のプロセスをデバッガに追加することが可能です。メニュー・アイテム デバッグ(_D)プロセスに取り込む(_A)… を選択して下さい。すると、システムで起動中の全プロセスの一覧が表示されます。

#### プロセス追加ダイアログ

プロセス追加ダイアログ

追加するプロセスを選択して OK をクリックして下さい。そして先に実行型式ファイル (とシンボル・テーブル) がデバッガの中に読み込まれていることを確認して下さい。

複数のクェスチョンマーク (??) がデバッグ作業中に表示されると、追加したプロセスと実行型式ファイルが一致していない状態です。

### コア・ファイルの読み込み

メニュー・アイテム デバッグ(_D)core ファイルの読み込み(_C)… を選択してコア・ファイルを読み込みます。ファイル選択ダイアログの中からコア・ファイルを選択して、OK をクリックして下さい。コア・ファイルを読み込む時に、先に実行型式ファイル (とシンボル・テーブル) が読み込まれていることを確認して下さい - そうでないと、デバッグがおかしくなるかもしれません！

複数のクェスチョンマーク (??) がデバッグ作業中に表示されると、追加したプロセスと実行型式ファイルが一致していない状態です。

## 実行

デバッガの中でプログラムを実行すると、細部までコントロールすることができます。 プログラムをステップ単位、あるいはブレークポイントを設定した場所まで連続して実行することができます。 このような実行は、プログラムの動作を追跡するために必要不可欠です。 ビデオの編集作業のように前に進んで、一時停止して、停止するといった感じで、プログラムを スローモーション で実行することができます。

デバッガの中でプログラムを実行する方法は先のセクションで紹介します。

### ステップ単位で実行する (ステップ・イン)

ステップ単位で実行するというのは、(停止した場所から) プログラムの一行分の命令を実行して制御を戻すことです。一つ以上の関数を含む命令が実行されると、デバッガは (その関数の内部に入って) 一行分の命令を実行します。命令が実行され制御が戻ると、いろいろなプログラムのパラメータを調査することが可能です。

ステップ単位で実行を開始しようとした時にプログラムが起動されていない場合は、プログラムが自動的に起動されてプログラムの一番最初の命令 (main() 関数にある一番最初の命令) で停止した状態になります。

メニュー・アイテム デバッグ(_D)実行(_E)ステップイン(_I) を選択するか デバッグ・ツールバー にある ステップ・イン アイコンをクリックすると、プログラムをステップ単位で実行させます。

### ステップ単位で実行する (ステップ・オーバー)

ステップ・オーバー は実行される命令として関数の内部に入らないことを除くと、ステップ・イン とほぼ同じです。命令は一行単位で実行されます。

メニュー・アイテム デバッグ(_D)実行(_E)ステップオーバー(_V) を選択するか デバッグ・ツールバー にある ステップ・オーバー アイコンをクリックすると、プログラムをステップ・オーバー単位で実行させます。

### ステップ単位で実行する (ステップ・アウト)

ステップ・アウト は現在デバッグ中の関数が終了するまで実行します。プログラムは関数から外にでると停止します。実際ステップ・アウトはステップ単位の実行ではないですが、その理由は一行単位で命令を実行しないからです - つまり、制御がその関数の呼び出し元に戻るまで関数全体を実行することを意味します。

メニュー・アイテム デバッグ(_D)実行(_E)ステップアウト(_O) を選択するか デバッグ・ツールバー にある ステップ・アウト アイコンをクリックすると、プログラムをステップ・アウト単位で実行させます。

### 実行/続行

このオプションはブレークポイントが設定されている場所まで、あるいはプログラムが終了する場所までそのプログラムの実行を続行します。

プログラムが未だ起動されていない場合は、プログラムが自動的に起動してブレークポイントが設定されている場所か、プログラムが終了する場所に到達するまで実行します。

メニュー・アイテム デバッグ(_D)実行(_E)実行/続行(_C) を選択するか デバッグ・ツールバー にある 実行/続行 アイコンをクリックすると、プログラムの実行を続けます。

### プログラムの停止

このオプションはデバッグ対象のプログラムを強制終了します。追加したプロセスを停止することはできないので注意して下さい。

メニュー・アイテム デバッグ(_D)プログラムの停止(_T) を選択するか デバッグ・ツールバー にある プログラムの停止 アイコンをクリックすると、プログラムの実行が終了します。

### プログラムの再起動

このオプションは、プログラムを停止して再度起動します。有効な全てのブレークポイントは残ったままです。追加したプロセスは再起動することができないので注意して下さい。

メニュー・アイテム デバッグ(_D)プログラムの再起動(_R) を選択すると、プログラムを再起動します。

## ブレークポイント

プログラムをデバッグする時、特定の場所でプログラムの実行と停止することができたら便利です。そうすると、その場所でプログラムを調査することができるからです。ブレークポイントはこれを可能にしてくれます。ブレークポイントはソースファイルの別々の場所にセットすることが可能で、そのあとにプログラムを実行することができます。ブレークポイントの場所にくると、式を評価したり変数を調査したり、スタックをたどったりするたにプログラムの実行は一時停止します。

### ブレークポイント・ダイアログ

ブレークポイント・ダイアログ

場所、これはソースファイルの中のコードの場所を指しています。場所 は次のような書式で指定します。

1. File_name:Line_number

2. Function_name

3. File_name:Function_name

最初の書式は簡単です - 場所はソースファイル File_name の中にある行番号 Line_number を表します。二番目は関数 Function_name の先頭を表します。三番目は、プログラムの中で同じ名前の関数 Function_name が一つ以上ある場所で使われる表記であることを除けば、二番目とほぼ同じです。File_name が提供する別の関数として認識するので、ファイル File_name の中にある関数 Function_name を表します。

二つのパラメータが各ブレークポイントで使われます:

1. ブレーク条件

2. パスする回数

ブレーク条件 は論理値を評価する正しい C 言語スタイルの式です - つまり、この式を評価すると真(1) か 偽(0) のどちらかを返します。もし最後の評価値が論理値ではない場合、適切な論理値にキャストされます。

実行中にブレークポイントに遭遇する度に、ブレーク条件が評価されます。デバッガはその評価結果が真 (1) の場合にのみ実行を停止し、対して偽 (0) の時はブレークポイントがなかったかのように実行を続けます。

ブレーク条件 のデフォルト値はつねに真 (1) です。そのため、デバッガはブレークポイントが設定されている場所で実行をデフォルトで停止します。

パスする回数 は (符号なし) 整数値で、ブレークポイントを無視する回数をデバッガに指示します。パスする回数 の優先度は ブレーク条件 よりも高いです。パスする回数 がゼロに到達した場合にのみ (いくつかの条件があるとすると)、デバッガは ブレーク条件 を評価します。条件が無い場合、デバッガは パスする回数 がゼロになった時点で実行を停止します。

パスする回数 のデフォルト値は０です。ブレークポイントに遭遇した時にカウントされます。

### ブレークポイントの追加または設定

メニュー・アイテム 表示(_V)ブレークポイント(_B) または デバッグ(_D)ブレークポイント(_B)ブレークポイント(_B)… を選択すると ブレークポイント編集ウィンドウ を開くことができます。追加 ボタンをクリックして下さい。ダイアログが表示されます。

#### ブレークポイント追加ダイアログ

ブレークポイント追加ダイアログ

ブレークポイントをセットする場所を入力して下さい。オプションとして、ブレーク条件 と パスする回数 を該当するエントリ・ボックスに入力して下さい。OK をクリックするとブレークポイントがセットされます。 breakpoint.

エディタの中でブレークポイントがある行の関数名が強調表示されるので、メニュー・アイテム デバッグ(_D)ブレークポイント(_B)ブレークポイント ON (あるいは、Debug Toolbar の中にある カーソル行のブレークポイント表示の切り替え ボタンをクリックして下さい) を選択して下さい。

### ブレークポイントの編集

メニュー・アイテム 表示(_V)ブレークポイント(_B) または デバッグ(_D)ブレークポイント(_B)ブレークポイント(_B)… を選択して ブレークポイント編集ウィンドウ を開いて下さい。編集するブレークポイントを選択して 編集 ボタンをクリックします。するとダイアログが表示されます。

#### ブレークポイント編集ダイアログ

ブレークポイント編集ダイアログ

エントリを編集して OK ボタンをクリックし変更を適用して下さい。

### ブレークポイントの削除

メニュー・アイテム 表示(_V)ブレークポイント(_B) または デバッグ(_D)ブレークポイント(_B)ブレークポイント(_B)… を選択して ブレークポイント編集ウィンドウ を開いて下さい。編集するブレークポイントを選択して 削除 ボタンをクリックします。するとそのブレークポイントが削除されます。

全てのブレークポイントを削除する場合は 全て削除 ボタンをクリックして下さい。

### ブレークポイントの有効/無効の切り替え

メニュー・アイテム 表示(_V)ブレークポイント(_B) または デバッグ(_D)ブレークポイント(_B)ブレークポイント(_B)… を選択して ブレークポイント編集ウィンドウ を開いて下さい。有効または無効にするブレークポイントを選択して 有効にする ボタンをクリックします。するとそのブレークポイントが現在の状態に応じて、有効または無効になります。

ブレークポイントの全てを有効または全てを無効にする場合は 全て有効 または 全て無効 ボタンをクリックして下さい。

#### 注記

デバッグを起動すると、全てのブレークポイントがセットされます。(ブレークポイントよりも新しいソースファイルにある) 古いブレークポイントは無効になります。

## 式を使ったデバッグ

FIXME:

### 式の評価

プログラムから制御が戻った時 - 場合によってはブレークポイントの場所で - 式を評価したりプログラムの中の変数の値を検証したりすることが可能です。メニュー・アイテム デバッグ(_D)検証/評価(_P) … を選択するか、Debug Toolbar の中にある 検証 ボタンをクリックして下さい。式の検証ダイアログがポップアップして表示されます。正しい C 言語スタイルの式、あるいは変数名を入力して OK ボタンをクリックして下さい。

#### 検証/評価ダイアログ

検証/評価ダイアログ

評価の結果を表示したウィンドウが表示されます。

#### 評価の結果

評価の結果

あるいは、エディタの中で式を強調表示し上述の作業を行うことが可能です。検証ダイアログ の中で式を入力するのを支援します。

式は C 言語スタイルで正しく入力し、プログラムからの関数呼び出し、ライブラリ呼び出し、システムコール、などなどを含めることも可能です。

### 式の監視

式の調査または評価は一度だけ結果を返します。変数や式の連続的な監視には、式の監視 を使用して下さい。

監視する全ての式と変数を追加して下さい。これらの値は自動的に更新し 式の監視ウィンドウ に表示されます。

#### 式の監視ウィンドウ

評価の監視

#### 監視する式を追加する

メニュー・アイテム 表示(_V)監視ウィンドウ(_W) を選択して下さい。式の監視ウィンドウ の上を右クリックすると オペレーション・メニュー が開きます。メニュー・アイテム 追加 をクリックして下さい。式の入力待ちダイアログが表示されます。式を入力して OK ボタンをクリックして下さい。

##### 式の追加ダイアログ

式の追加ダイアログ

エディタ内で選択した式が先に追加したものよりも優先度が高い場合は、自動的にダイアログの中に表示されます。

#### 監視する式を削除する

メニュー・アイテム 表示(_V)監視ウィンドウ(_W) を選択して下さい。式の監視ウィンドウ の上を右クリックすると オペレーション・メニュー が開きます。メニュー・アイテム 削除 をクリックするとエントリが削除されます。

#### 監視のクリア

メニュー・アイテム 表示(_V)監視ウィンドウ(_W) を選択して下さい。式の監視ウィンドウ の上を右クリックすると オペレーション・メニュー が開きます。メニュー・アイテム クリア をクリックすると更新またはクリアされます。

## スタック・トレース

### スタック・ウィンドウ

スタック・トレース・ウィンドウ はプログラムのスタックの内容を表示します。全ての関数の一覧とそれらの関数が呼び出された際に引き渡された全ての引数を一覧表示します。またそれらの関数が呼び出された回数も表示されます。この回数は フレーム と呼ばれます。トレースの中の各呼び出しは異なるフレームの中に存在します。これはフレーム 0 (最後に呼び出された関数を表す) から始まって 関数呼び出しが深くなるにつれて大きくなります。

メニュー・アイテム 表示(_V)スタック(_S) を選択して、デバッグしていたプログラムのスタック・トレースを開いて下さい。

#### スタック・トレース・ウィンドウ

スタック・トレース・ウィンドウ

スタックトレースの中で小さい矢印が、現在選択されているフレームを指しています。デフォルトで、これはフレーム 0 を指し、それは最後に呼び出された関数です。式や変数の検証/評価では、この選択されたフレームを参照することになります。評価された変数または式のスコープ (適用範囲) は選択されたフレームにのみ限定されています。監視する式にも同様に適用されます。

### 現在のフレームに対する設定

スタック・トレースの中にあるフレームをダブル・クリックすると、指定したフレームが現在のフレームとしてセットされます (矢印はそのフレームを指し、現在のフレームであることを意味することになります)。あるいは、スタック・トレース・ウィンドウ の上で右クリックして オペレーション・メニュー を開き、メニュー・アイテム フレームセット を選択すると、そのフレームがセットされます。

### 現在のフレームに対する情報

メニュー・アイテム デバッグ(_D)情報(_I)現在のフレーム(_C) を選択すると、現在選択しているフレームについての情報を取得することが可能です。現在のフレームに対する情報を表示したウィンドウが表示されます。

#### 現在のフレームに対する情報

現在のフレームに対する情報

### スタック・トレースの更新

オペレーション・メニュー (スタック・トレース・ウィンドウ の上で右クリックする) のメニュー・アイテム 更新 を選択すると スタック・トレース・ウィンドウ をリフレッシュします。

## その他

デバッガのあまり使われないその他の機能がいくつかありますが、以外と便利な機能なのでご紹介します。

### カーネル・シグナル

カーネル・シグナルはプロセスと Linux の間でやりとりをする一つの手段です。プログラムで利用可能なシグナルの一覧は、メニュー・アイテム 表示(_V)カーネルシグナル(_K) を選択すると表示することができます。システムで利用可能な全てのシグナルについて、短い説明とともに一覧表示するウィンドウが開きます。

#### カーネル・シグナル・ウィンドウ

カーネル・シグナル・ウィンドウ

シグナルを受け取った時に何を行うかを指示する三つの情報があります:

1. 停止 - これはプログラムがシグナルを受け取った時に実行を停止する (かつ制御を戻す) かどうかを、デバッガに指示するものです。

2. 表示 - これは受け取ったシグナルを表示するかどうかを、デバッガに指示するものです。

3. パス - これはプログラムが受け取ったシグナルを無視するかどうかを、デバッガに指示するものです。

#### シグナル受信時の動作を変更する

特定のシグナルを受信した時にそれに対応するデバッガの動作 (前述の三つの指示) を変更する場合は、一覧からシグナルを選択して右クリックして オペレーション・メニュー を開きます。そしてメニュー・アイテム シグナルの変更 を選択して下さい。するとダイアログが開きます。三つの指示を設定し変更を適用する場合は OK ボタンをクリックして下さい。

##### カーネル・シグナル変更ダイアログ

カーネル・シグナル変更ダイアログ

#### プログラムにシグナルを送信する

明示的にデバッグ中のプログラムにシグナルを送信する場合は、一覧からシグナルを選択して右クリックして オペレーション・メニュー を開きます。そしてメニュー・アイテム シグナル送信 を選択して下さい。すると確認ダイアログが開きます。プログラムに送信するシグナルを確認して OK ボタンをクリックして下さい。

#### シグナル一覧の更新

(カーネル・シグナル・ウィンドウ の上で右クリックして表示される) オペレーション・メニュー からメニュー・アイテム 更新 を選択して、カーネル・シグナル・ウィンドウ をリフレッシュして下さい。

### CPU レジスタ情報

CPU (マイクロプロセッサ) の内部レジスタの内容を調査することが可能です。メニュー・アイテム 表示(_V)レジスタ(_R) を選択して下さい。マイクロプロセッサ内の利用可能な全てのレジスタとそれに対する内容が表示されたウィンドウが開きます。

#### CPU レジスタ・ウィンドウ

CPU レジスタ・ウィンドウ

### 直接ライブラリを読み込む

プログラムで使用している動的ライブラリの一覧を取得する場合は、メニュー・アイテム 表示(_V)共有ライブラリ群(_L) を選択して下さい。すると、プログラムがメモリに読み込んだ全ての共有ライブラリの一覧を表示したウィンドウが開かれます。またシンボル・テーブルも一緒に読み込んでいるかどうか (Yes/No) も表示されます。

#### 共有ライブラリ・ウィンドウ

共有ライブラリ・ウィンドウ

### プログラムへの割り込み

プログラムが動作中でかつ制御を保持している間、デバッグ作業を行うことはできません。プログラムが動作中に制御を取得する場合は、メニュー・アイテム デバッグプログラムの割り込み(_I) を選択して下さい。プログラムに割り込んで制御をデバッガに戻します。

適切に割り込みが行われるために、割り込みシグナル (SIGINT) に対応するデバッガの動作を [ 停止:Yes, 表示:Yes, パス:No ] に設定して下さい。これはデフォルトです。