この章では、dbx による C++ の例外の処理方法と C++ テンプレートのデバッグについて説明します。これらの作業を実行するために使用するコマンドの要約とコード例も示します。
この章は次の各節から構成されています。
C++ プログラムのコンパイルの詳細については、「最適化コードのデバッグ」を参照してください。
この章では C++ デバッグの 2 つの特殊な点を中心に説明しますが、dbx を使用すると、C++ プログラムのデバッグに次の機能を利用することができます。
クラス定義の検索
継承されたデータメンバーの出力または表示
オブジェクトポインタに関する動的情報の検索
仮想関数のデバッグに関する情報の検索
実行時型情報の使用
クラスのすべてのメンバー関数に対するブレークポイントの設定
多重定義されたすべてのメンバー関数に対するブレークポイントの設定
多重定義されたすべての非メンバー関数に対するブレークポイントの設定
多重定義された関数/データメンバーの処理
特定オブジェクトのすべてのメンバー関数に対するブレークポイントの設定
これらの詳細については、索引の C++ の下の項目を参照してください。
プログラムは例外が発生すると実行を停止します。例外は、ゼロによる除算や配列のオーバーフローといったプログラムの障害を知らせるものです。例外を処理するには、ブロックを設定して、コードのどこかほかの場所で起こった式による例外を捕獲できます。
プログラムのデバッグ中、dbx を使用すると次のことが可能になります。
スタックを解放する前に処理されていない例外を捕獲する
予期できない例外を捕獲する
スタックを解放する前に、特定の例外が処理されたかどうかに関係なく捕獲する
特定の throw がプログラム内の特定の位置で起こった場合、それが捕獲される場所を決める
送出点での停止後に step を実行すると、制御はスタックの解放中に実行された最初のデストラクタの初めに返されます。スタックの解放中に実行されたデストラクタから step を実行して出ると、制御は次のデストラクタの初めに返されます。すべてのデストラクタが実行されたときに step を実行すると、送出を処理する捕獲ブロックに移動します。
このコマンドは、例外の型を表示するために使用します。この変数は、デバッグ中いつでも使用することができます。-d を使用すると、派生型が示されます。-d を使用しないと静的な型が示されます。このコマンドは、dbxenv 変数 output_dynamic_type の設定を上書きします。
スタックを解放する前に、特定の型の例外を阻止または捕獲できます。このコマンドを引数を付けずに使用すると、阻止される型がリストで示されます。-a を使用すると、すべての送出が阻止されます。阻止リストに型を追加するには typename を使用します。-x を使用すると、特定の型を阻止から除外することができます。
たとえば、int を除くすべての型を阻止するには、次のように入力します。
(dbx) intercept -a (dbx) intercept -x int
このコマンドは、阻止リストから例外の型を削除するために使用します。引数を付けずにこのコマンドを使用すると、阻止されている型のリストが示されます (intercept に同じ)。-a を使用すると、リストから阻止された型すべてが削除されます。typename を使用すると、阻止リストから 1 つの型を削除することができます。-x は、特定の型を阻止から除外することをやめるために使用します。
このコマンドは、typename の例外が実行の現時点で送出された場合に、どこで捕獲されるかを報告するものです。このコマンドは、例外がスタックのトップフレームから送出された場合に何が起こるかを検出する場合に使用します。
typename を捕獲した元の送出の行番号、関数名、およびフレーム数が表示されます。
次の例は、例外を含むサンプルプログラムを使用して、dbx で例外処理がどのように実行されるかを示しています。型 int の例外が、関数 bar で送出されて、次の捕獲ブロックで捕獲されています。
1 #include <stdio.h>
2
3 class c {
4 int x;
5 public:
6 c(int i) { x = i; }
7 ‾c() {
8 printf("destructor for c(%d)¥n", x);
9 }
10 };
11
12 void bar() {
13 c c1(3);
14 throw(99);
15 }
16
17 int main() {
18 try {
19 c c2(5);
20 bar();
21 return 0;
22 }
23 catch (int i) {
24 printf("caught exception %d¥n", i);
25 }
26 }
サンプルプログラムからの次のトランスクリプトは、dbx の例外処理機能を示しています。
(dbx) intercept int
(dbx) intercept
-unhandled -unexpected int
(dbx) stop in bar
(2) stop in bar(void)
(dbx) run
実行中: a.out
(プロセス id 1652)
bar で停止しました 行番号 13 ファイル "foo.cc"
13 c c1(3);
(dbx) whocatches int
int が行番号 24 で捕獲されました、関数 main (フレーム番号 2)
(dbx) whocatches c
dbx: class c の実行時型情報がありません (送出も捕獲もされていない)
(dbx) cont
例外の型 int が行番号 24 で捕獲されました、関数 main (フレーム番号 4)
_ex_dbg_will_throw で停止しました アドレス 0xef724344
0xef724344: _ex_dbg_will_throw : jmp %o7 + 0x8
現関数 :bar
14 throw(99);
(dbx) step
c::‾c で停止しました 行番号 8 ファイル "foo.cc"
8 printf("destructor for c(%d)¥n", x);
(dbx) step
destructor for c(3)
c::‾c で停止しました 行番号 9 ファイル "foo.cc"
9 }
(dbx) step
c::‾c で停止しました 行番号 8 ファイル "foo.cc"
8 printf("destructor for c(%d)¥n", x);
(dbx) step
destructor for c(5)
c::‾c で停止しました 行番号 9 ファイル "foo.cc"
9 }
(dbx) step
main で停止しました 行番号 24 ファイル "foo.cc"
24 printf("caught exception %d¥n", i);
(dbx) step
caught exception 99
main で停止しました 行番号 26 ファイル "foo.cc"
26 }
dbx は C++ テンプレートをサポートしています。クラスおよび関数テンプレートを含むプログラムを dbx に読み込み、クラスや関数に対して使用する任意の dbx コマンドをテンプレートに対して次のように呼び出すことができます。
クラスまたは関数テンプレートのインスタンス化にブレークポイントを設定する
すべてのクラスおよび関数テンプレートのインスタンス化のリストを出力する
テンプレートおよびインスタンスの定義を表示する
メンバーテンプレート関数と関数テンプレートのインスタンス化を呼び出す
関数テンプレートのインスタンス化の値を出力する
関数テンプレートのインスタンス化のソースコードを表示する
次のコード例は、クラステンプレート Array とそのインスタンス化、および関数テンプレート square とそのインスタンス化を示しています。
この例の内容は次のとおりです。
Array はクラステンプレート
square は関数テンプレート
Array<int> はクラステンプレートインスタンス化 (テンプレートクラス)
Array<int>::getlength はテンプレートクラスのメンバー関数
square(int, int*) と square(double, double*) は関数テンプレートのインスタンス化 (テンプレート関数)
1 template<class C> void square(C num, C *result)
2 {
3 *result = num * num;
4 }
5
6 template<class T> class Array
7 {
8 public:
9 int getlength(void)
10 {
11 return length;
12 }
13
14 T & operator[](int i)
15 {
16 return array[i];
17 }
18
19 Array(int l)
20 {
21 length = l;
22 array = new T[length];
23 }
24
25 ‾Array(void)
26 {
27 delete [] array;
28 }
29
30 private:
31 int length;
32 T *array;
33 };
34
35 int main(void)
36 {
37 int i, j = 3;
38 square(j, &i);
39
40 double d, e = 4.1;
41 square(e, &d);
42
43 Array<int> iarray(5);
44 for (i = 0; i < iarray.getlength(); ++i)
45 {
46 iarray[i] = i;
47 }
48
49 Array<double> darray(5);
50 for (i = 0; i < iarray.getlength(); ++i)
51 {
52 iarray[i] = i * 2.1;
53 }
54
55 return 0;
56 }
プログラムをデバッグする場合、以下に示す任意の例外処理コマンドを呼び出すことができます。
以下に示すコマンドは、テンプレートおよびインスタンス化されたテンプレートに使用します。クラスまたは型定義がわかったら、値の出力、ソースリストの表示、またはブレークポイントの設定を行うことができます。
whereis は、関数テンプレートまたはクラステンプレートの、インスタンス化された関数やクラスの出現すべてのリストを出力するために使用します。
(dbx) whereis Array クラステンプレートのインスタンス: 'Array<int> クラステンプレートのインスタンス: 'Array<double> クラステンプレート: `sample`sample.cc`Array
(dbx) whereis square 関数テンプレート: `sample`square
関数テンプレートおよびクラステンプレートと、インスタンス化された関数やクラスの定義を出力するために使用します。
(dbx) whatis Array template<class T> class Array ; 完全なテンプレート宣言を得るために次を実行してください: 'whatis -t Array<int>';
(dbx) whatis square template<class C> void square(C num, C *result);
クラステンプレートのインスタンス化の場合は、次のように入力します。
(dbx) whatis -t Array<int>
class Array<int> {
public:
int Array<int>::getlength();
int &Array<int>::operator[](int i);
Array<int>::Array<int>(int l);
Array<int>::‾Array<int>();
private:
int length;
int *array;
};
テンプレートクラスのすべてのメンバー関数を停止するには、次のように入力します。
(dbx)stop inclass Array (2) stop inclass Array
stop inclass を使用して、特定のテンプレートクラスのメンバー関数すべてにブレークポイントを設定します。
(dbx) stop inclass Array<int> (2) stop inclass Array<int>
stop in を使用して、あるテンプレートクラスのメンバー関数、またはテンプレート関数にブレークポイントを設定します。
インスタンス化されたクラステンプレートの場合は、次のように入力します。
(dbx) stop in Array<int>::Array<int>(int l) (2) stop in Array<int>::Array<int>(int)
call は、スコープ内で停止した場合に、インスタンス化された関数またはクラステンプレートメンバー関数を明示的に呼び出すために使用します。dbx が正しいインスタンスを選択できない場合は、メニューを使用して正しいインスタンスを選択できます。
(dbx) call square(j,i)
print を使用して、インスタンス化された関数またはクラステンプレートメンバー関数を評価します。
(dbx) print iarray.getlength() iarray.getlength() = 5
(dbx) whatis this
class Array<int> *this;
(dbx) print *this
*this = {
length = 5
array = 0x21608
}
list を使用して、指定のインスタンス化された関数のソースリストを出力します。
(dbx) list square(int, int*)