プログラム・データの調査
この項では、プログラム・データを調査、テスト、および変更する方法を説明します。
シグナルの処理
dbx デバッグ・プログラムは、 シグナルをユーザーのプログラムに送信する前に、 トラッピングまたは無視することができます。 ユーザーのプログラムがシグナルを受信する必要があるたびに、 dbx プログラムは通知を受けます。 シグナルは、無視する必要がある場合、ユーザーのプログラムに渡されます。それ以外の場合、dbx プログラムはプログラムを停止し、シグナルがトラッピングされたことをユーザーに通知します。 dbx プログラムは、SIGTRAP シグナルがデバッグ・プロセス外のプロセスから送信された場合、このシグナルを無視できません。 マルチスレッド・プログラムでは、シグナルは pthread_kill サブルーチンを介して特定のスレッドに送信することができます。デフォルトでは、dbx プログラムは停止し、シグナルがトラッピングされたことをユーザーに通知します。 ignore サブコマンドを使用してシグナルをユーザーのプログラムに渡すように要求した場合、dbx プログラムはそのシグナルを無視してスレッドに渡します。 デフォルトの処理を変更するには、catch サブコマンドおよび ignore サブコマンドを使用してください。
次の例では、プログラムは SIGGRANT と SIGREQUEST を使用してリソースの割り当てを処理しています。 dbx プログラムが、以下のいずれかのシグナルを受信しても継続するようにするには、 次のように入力します。
(dbx) ignore GRANT
(dbx) ignore SIGREQUEST
(dbx) ignore
CONT CLD ALARM KILL GRANT REQUEST$sigblock 変数を設定した場合、 dbx デバッグ・プログラムはシグナルをユーザーのプログラムに対してブロックすることができます。 デフォルトでは、dbx プログラムを介して受信したシグナルは、ソース・プログラム、または dbx ObjectFile パラメーターで指定されたオブジェクト・ファイルに送信されます。 set サブコマンドを使用して $sigblock 変数が設定されている場合、dbx プログラムが受信したシグナルはソース・プログラムに渡されません。 シグナルをプログラムに送信する必要がある場合には、 cont サブコマンドを使用し、 オペランドとしてシグナルを指定してください。
この機能を使用すれば、dbx デバッグ・プログラムの下で実行中のプログラムの実行に割り込むことができます。 プログラム状況を調査してから、通常どおり実行を継続することができます。 $sigblock 変数を設定しない場合、実行に割り込むと SIGINT シグナルがプログラムに送信されます。 実行が継続すると、これによって、シグナル・ハンドラーが存在していれば、 シグナル・ハンドラーに分岐します。
次のプログラム例は、$sigblock 変数を設定した場合に、dbx デバッグ・プログラムを使用する実行がどのように変更されるかを示しています。
#include <signal.h>
#include <stdio.h>
void inthand( ) {
printf("¥nSIGINT received¥n");
exit(0);
} main( )
{
signal(SIGINT, inthand);
while (1) {
printf(".");
fflush(stdout);
sleep(1);
}
}dbx プログラムを伴う次のサンプル・セッションは、上記のプログラムをソース・ファイルとして使用しています。 プログラムの最初の実行では、$sigblock 変数を設定していません。 再実行時に、$sigblock 変数を設定しています。 右側の不等号括弧内にコメントが示してあります。
dbx version 3.1.
Type 'help' for help.
reading symbolic information ...
(dbx) run
.........^C <User pressed Ctrl-C here!>
interrupt in sleep at 0xd00180bc
0xd00180bc (sleep+0x40) 80410014 1 r2,0x14(r1)
(dbx) cont SIGINT received
execution completed
(dbx) set $sigblock
(dbx) rerun
[ looper ]
..............^C <User pressed Ctrl-C here!>
interrupt in sleep at 0xd00180bc
0xd00180bc (sleep+0x40) 80410014 1 r2,0x14(r1)
(dbx) cont
....^C <Program did not receive signal, execution continued>
interrupt in sleep at 0xd00180bc
0xd00180bc (sleep+0x40) 80410014 1 r2,0x14(r1)
(dbx) cont 2 <End program with a signal 2>
SIGINT received execution completed
(dbx)プロシージャーの呼び出し
さまざまな引数をテストするために、dbx プログラムからユーザーのプログラム・プロシージャーを呼び出すことができます。 さらに、デバッグ時に役立つようにデータをフォーマット設定する診断ルーチンも呼び出すことができます。 プロシージャーを呼び出すには、call サブコマンドまたは print サブコマンドを使用します。
スタック・トレースの表示
プログラム停止に先行するプロシージャー・コールをリストするには、 where コマンドを使用してください。
次の例で、実行可能オブジェクト・ファイル hello は、 2 つのソース・ファイルおよび、標準プロシージャー main を 含む 3 つのプロシージャーから構成されています。 プログラムは、 プロシージャー sub2 内のブレークポイントで停止します。
(dbx) run
[1] stopped in sub2 at line 4 in file "hellosub.c"
(dbx) where
sub2(s = "hello", n = 52), line 4 in "hellosub.c"
sub(s = "hello", a = -1, k = delete), line 31 in "hello.c"
main(), line 19 in "hello.c"スタック・トレースは、逆順でコールを示しています。 ボトムから開始して、 以下のイベントが発生しています。
- シェルが main を呼び出しました。
- main が行 19 で値 s = "hello"、a = -1、および k = delete を指定して、sub プロシージャーを呼び出しました。
- sub が行 31 で値 s = "hello" および n = 52 を指定して、sub2 プロシージャーを呼び出しました。
- プログラムは、sub2 プロシージャーの行 4 で停止しました。
where 0 1 を使用します。 (dbx)run
[1] stopped in sub2 at line 4 in file "hellosub.c"
(dbx) where 0 1
sub2(s = "hello", n = 52), line 4 in "hellosub.c"
sub(s = "hello", a = -1, k = delete), line 31 in "hello.c"注: デバッグ・プログラム変数 $noargs を設定すると、プロシージャーに渡された引数の表示をオフにすることができます。 各アクティブ関数またはプロシージャーに設定されているページ枠番号とレジスターを表示するには、デバッグ・プログラム変数 $stack_details を設定します。
また、サブコマンド up、down、および frame を使用してスタックの一部を表示することもできます。
変数の表示と変更
式を表示するには、print サブコマンドを使用します。 変数の名前および値を印刷するには、 dump サブコマンドを使用します。 与えられたプロシージャーがピリオドである場合には、すべてのアクティブ変数が印刷されます。 PATTERN パラメーターが指定される場合、指定の記号のみが表示されるのではなく、PATTERN と一致するすべての記号が印刷されます。 変数の値を変更するには、 assign サブコマンドを使用します。
次の例では、C プログラムに値が 7 の自動整変数 x と sub2 プロシージャー内の s および n パラメーターがあります。
(dbx) print x, n
7 52
(dbx) assign x = 3*x
(dbx) print x
21
(dbx) dump
sub2(s = "hello", n = 52)
x = 21スレッド関連情報の表示
ユーザーのスレッド、mutex、条件、および属性オブジェクトに関する情報を表示するには、thread、mutex、condition、および attribute サブコマンドを使用します。 また、print サブコマンドもこれらのオブジェクトに使用することができます。 次の例で、実行スレッドは thread 1 です。 ユーザーは現在のスレッドを thread 2 に設定し、各スレッドをリストし、thread 1 に関する情報を印刷し、 最後に、いくつかのスレッド関連オブジェクトに関する情報を印刷します。
(dbx) thread current 2
(dbx) thread
thread state-k wchan state-u k-tid mode held scope function
*$t1 run running 12755 u no pro main
>$t2 run running 12501 k no sys thread_1
(dbx) print $t1
(thread_id = 0x1, state = run, state_u = 0x0, tid = 0x31d3, mode = 0x1, held = 0x0, priority = 0x3c,
policy = other, scount = 0x1, cursig = 0x5, attributes = 0x200050f8)
(dbx) print $a1,$c1,$m2
(attr_id = 0x1, type = 0x1, state = 0x1, stacksize = 0x0, detachedstate = 0x0, process_shared = 0x0,
contentionscope = 0x0, priority = 0x0, sched = 0x0, inherit = 0x0, protocol = 0x0, prio_ceiling = 0x0)
(cv_id = 0x1, lock = 0x0, semaphore_queue = 0x200032a0, attributes = 0x20003628)
(mutex_id = 0x2, islock = 0x0, owner = (nil), flags = 0x1, attributes = 0x200035c8)名前の有効範囲化
現在の関数の静的有効範囲を使用して、名前が最初に解決されます。 名前が最初の有効範囲に定義されていない場合、動的有効範囲が使用されます。 静的検索および動的検索が結果を生成しない場合、任意のシンボルが選択され、 メッセージ「using Qualified Name」が印刷されます。 ネーム・レゾリューション・プロシージャーを指定変更するには、 ブロック名 (例えば、Module.Variable ) を使用して ID を修飾します。 ソース・ファイルは、接尾部なしのファイル名によって指定されるモジュールとして処理されます。 例えば、hello.c ファイル内の sub プロシージャーで宣言されている x 変数は、完全修飾名 hello.sub.x を持っています。プログラム自体は名前として 1 つのピリオドを持っています。
which および whereis サブコマンドは、同じ名前の複数のシンボルが存在する場合に、 検出するシンボルを決定する場合に役立ちます。
式での演算子と修飾子の使用
dbx プログラムは広範囲の式を表示することができます。 C 構文の共通のサブセット、および FORTRAN のいくつかの拡張機能を使用して式を指定します。
- * (アスタリスク) または ^ (脱字記号)
- 間接またはポインター参照解除を示します。
- [ ] (大括弧) または ( ) (括弧)
- 添え字配列式を示します。
- . (ピリオド)
- このフィールド参照演算子は、ポインターおよび構造体とともに使用します。 これによって、C 演算子 -> (矢印) は使用できますが、不要になりました。
- & (アンパーサンド)
- 変数のアドレスを獲得します。
- .. (2 つのピリオド)
- 配列のサブセクションを指定する場合、上限と下限を分離します。 例えば、n[1..4]。
以下のタイプの操作が式内で有効です。
- 代数
- =、-、*、/ (浮動小数点除算)、div (整数除算)、mod、exp (べき乗)
- ビット単位
- -、I、bitand、xor、~、<<、>>
- 論理
- or、and、not、 II、&&
- 比較
- <、>、<=、>=、<> または !=、= または ==
- その他
- sizeof
論理式と比較式は、stop および trace サブコマンドの条件として使用することができます。
式のタイプの検査
dbx デバッグ・プログラムは式のタイプを検査します。 式のタイプを指定変更するには、名前変更演算子またはキャスト演算子を使用します。 タイプの名前変更の形式は 3 つあります。
- Typename (Expression)
- Expression ¥ Typename
- (Typename) Expression
注: 構造体、共用体、 またはクラスとの間でキャストする場合、左寄せが行われます。 ただし、あるクラスから基本クラスへキャストする場合、C++ 構文規則に従います。
例えば、値が 97 の変数 x の名前を変更するには、次のように入力します。
(dbx) print char (x), x ¥ char, (char) x, x,
'a' 'a' 'a' 97以下の例は、 タイプの名前変更に関する (Typename) Expression 形式を使用する方法を示しています。
print (float) i
print ((struct qq *) void_pointer)->first_element以下の制約事項が dbx デバッグ・プログラムに関する C スタイルのタイプ・キャストに適用されます。
- Fortran タイプ (integer*1、integer*2、integer*4、logical*1、logical*2、logical*4 など) は 、キャスト演算子としてサポートされません。
- アクティブ変数が基本タイプまたはユーザー定義タイプと同じ名前を持っている場合、 そのタイプは C スタイルの型変換用のキャスト演算子として使用することができません。
whatis サブコマンドは ID の宣言を印刷します。 この ID は、ブロック名を使用して修飾できます。
列挙型、構造体、または共用体タグの宣言を印刷するには、$$TagName 構成を使用してください。
assign サブコマンド式のタイプは、 ユーザーが割り当てた変数のタイプと一致していなければなりません。 タイプが一致しない場合、エラー・メッセージが表示されます。 タイプの名前変更を使用して、式のタイプを変更してください。 タイプ検査を使用不可にするには、dbx デバッグ・プログラムの特殊な $unsafeassign 変数を設定してください。
小文字から大文字への変数の変換
デフォルトで、dbx プログラムは現在の言語に基づいてシンボルを大文字または小文字に変換します。 現在の言語が C、C++、または未定義の場合、 シンボルは大文字または小文字に変換されません。 現在の言語が Fortran の場合、シンボルは小文字変換されます。 プログラムが、debug フラグを指定してコンパイルしていないコードのセクション内にある場合、 現在の言語は未定義です。 デフォルトの処理を指定変更するには、 case サブコマンドを使用します。
引数を指定しないで case サブコマンドを使用すると、 現在の大文字小文字モードが表示されます。
Fortran コンパイラーは、すべてのプログラム・シンボルを小文字変換します。C コンパイラーは小文字変換しません。 ただし、Fortran コンパイラーの中には小文字シンボルを常に生成するとは限らないものもあります。 例えば、mod2 というモジュール内の proc1 というプロシージャーを仮定した場合、XLF Fortran コンパイラーは __mod2_MOD_proc1 シンボルを生成しますが、このシンボルは大/小文字混合です。 このような場合、dbx プログラム内にある大/小文字を大/小文字混合に変更しなければなりません。
特殊なデバッグ・プログラム変数による印刷出力の変更
print サブコマンドからさまざまな結果を取得するために、set サブコマンドを使用して、以下の特殊な dbx デバッグ・プログラム変数を設定できます。
- $hexints
- 整数式を 16 進数で印刷します。
- $hexchars
- 文字式を 16 進数で印刷します。
- $hexstrings
- 文字列自体ではなく、文字列のアドレスを印刷します。
- $octints
- 整数式を 8 進数で印刷します。
- $expandunions
- 共用体内の各フィールドを印刷します。
- $pretty
- C および C++ の複雑なタイプを pretty フォーマットで表示します。
- $print_dynamic
- 動的型の C++ オブジェクトを印刷します。
- $show_vft
- 仮想関数テーブルを印刷すると同時に、C++ オブジェクトを印刷します。
望ましい結果を得るために、デバッグ・プログラム変数を設定し、設定を解除します。 次に例を示します。
(dbx) whatis x; whatis i; whatis s
int x;
char i;
char *s;
(dbx) print x, i, s
375 'c' "hello"
(dbx) set $hexstrings; set $hexints; set $hexchars
(dbx) print x, i, s
0x177 0x63 0x3fffe460
(dbx) unset $hexchars; set $octints
(dbx) print x, i
0567 'c'
(dbx) whatis p
struct info p;
(dbx) whatis struct info
struct info {
int x;
double position[3];
unsigned char c;
struct vector force;
};
(dbx) whatis struct vector
struct vector {
int a;
int b;
int c;
};
(dbx) print p
(x = 4, position = (1.3262493258532527e-315, 0.0, 0.0),
c = '¥0', force = (a = 0, b = 9, c = 1))(dbx) set $pretty="on"
(dbx) print p
{
x = 4
position[0] = 1.3262493258532527e-315
position[1] = 0.0
position[2] = 0.0
c = '¥0'
force = {
a = 0
b = 9
c = 1
}
}
(dbx) set $pretty="verbose"
(dbx) print p
x = 4
position[0] = 1.3262493258532527e-315
position[1] = 0.0
position[2] = 0.0
c = '¥0'
force.a = 0
force.b = 9
force.c = 1show_vft を設定しないで、オブジェクトを print サブコマンドを使用して印刷する場合、仮想関数テーブル (VFT) は印刷されません。 これを設定すると、VFT が表示されます。 次に例を示します。
(dbx) p *d
B1:(int_in_b1 = 91)
B2:(int_in_b2 = 92)
(int_in_d = 93)
(dbx) p *b2
(int_in_b2 = 20)
(dbx)set $show_vft
(dbx) p *d
B1:(B1::f1(), int_in_b1 = 91)
B2:(D::f2(), int_in_b2 = 92)
(int_in_d = 93)
(dbx) p *b2
(B2::f2(), int_in_b2 = 20)
(dbx) print_dynamic を設定しない場合、オブジェクトは静的型 (ソース・コードに定義される) のテンプレートどおりに表示されます。 それ以外の場合、オブジェクトは動的型 (キャストが行われる前のオブジェクト) のテンプレートどおりに表示されます。 次に例を示します。
(dbx) r
[1] stopped in main at line 57
57 A *obj1 = new A();
(dbx) n
stopped in main at line 58
58 A *obj2 = new B();
(dbx) n
stopped in main at line 59
59 cout<<" a = "<<obj2->a<<" b = "<<obj2->b<<endl;
(dbx) p *obj2
(a = 1, b = 2)
(dbx)set $print_dynamic
(dbx) print *obj2
A:(a = 1, b = 2)
(c = 3, d = 4)
(dbx)