Rational Developer for System z バージョン 7.6

C および C++ プログラムのデバッグ

ここでは以下のトピックで、Debug Tool を使用して C および C++ プログラムを デバッグする方法を説明します。

例: C および C++ ブロックでの変数の参照とブレークポイントの設定

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

C および C++ コマンドに類似した Debug Tool コマンド

Debug Tool のコマンド言語は、C および C++ コマンドのサブセットであり、構文上の要件は同じです。Debug Tool では慣れている言語によって作業ができるため、新しいコマンド・セットを学習する必要はありません。

下の表では、Debug Tool 認識される C および C++ コマンドの解釈サブセット を示します。

コマンド 説明
block ({}) 複合コマンド・グループ
break ループまたは switch コマンドの終了
declarations セッション変数の宣言
do/while 繰り返しループ
expression 条件 (?) 演算子を除くすべての C の式
for 繰り返しループ
if 条件付きの実行
switch 条件付きの実行

このコマンドのサブセットは、現行のプログラム言語が C または C++ の場合にのみ有効です。

使用できる C および C++ コマンドのサブセットに加え、C および C++ が使用し認識する一連の予約されたキーワードがありますが、これらのキーワードは省略したり、変数名として使用したり、あるいはその他の ID として使用することはできません。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

Debug Tool による C および C++ 変数の使用

Debug Tool は、C または C++ で有効なすべてのプログラム変数を 処理することができます。その結果、セッション中の変数の値の割り当ておよび表示が可能になります。また、認識されている C の宣言でセッション変数を宣言して、テストの必要性に 合わせることもできます。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

C および C++ プログラム変数へのアクセス

Debug Tool は、コンパイラーによって作成されたシンボル・テーブルを使用して、名前からプログラム変数に関する情報を入手します。コンパイル時に TEST(SYM) の指定を 行っておけば、コンパイラーがシンボル・テーブルを作成するので、プログラム 内のすべての変数の参照ができるようになります。

注:
C++ の場合サブオプションはありません。シンボル情報は、TEST コンパイラー・オプションが指定されると、デフォルトにより生成されます。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

C および C++ の変数または式の値の表示

変数または式の値を表示するには、LIST コマンドを使用 します。LIST コマンドを使用すると、Debug Tool は変数の現行値 (必要な場合は名前も) を、 式の評価結果とともに記録して表示します。

例えば、プログラム変数 Xrow[X]、および col[X]、および行 25 でのその値を表示したいとします。 そこで、次のコマンドを出したとします。

AT 25 LIST ( X, row[X], col[X] ); GO;

Debug Tool は、行 25 にブレークポイントを設定し (AT)、プログラムの実行を開始し (GO)、行 25 で停止して、変数名とその値を表示します。

これらの値の加算結果を見るには、次のように入力してください。

AT 25 LIST ( X + row[X] + col[X] ); GO;

Debug Tool は、行 25 にブレークポイントを設定し (AT)、プログラムの実行を開始し (GO)、行 25 で停止して、式の結果を表示します。

複数のリストを出すときには、変数の間にコンマを置いてください。LIST コマンドを出すときに、変数名を表示したくない場合は、LIST UNTITLED と入力します。

次のようにして、printf 関数呼び出しによって 変数をリストすることもできます。

printf ("X=%d, row=%d, col=%d¥n", X, row[X], col[X]);

ただし、SET INTERCEPT ON FILE stdout を設定しないかぎり、printf からの出力はログ・ウィンドウには表示されず、ログ・ファイルにも記録されません。

C および C++ 変数への値の割り当て

C および C++ 変数に値を割り当てるには、代入式を使用します。代入式は、値を左辺オペランドに代入します。左辺オペランドは、更新可能な左辺値でなければなりません。左辺値は、検査して変更できるデータ・オブジェクトを表す式です。

C には、単純および複合の 2 つのタイプの代入演算子があります。単純代入演算子は、右辺オペランドの値を左辺オペランドに代入します。

注:
C で機能する代入演算子のみが C++ でも機能します。すなわち、多重定義演算子のサポートはありません。

次の例は、number の値を、構造 payroll のメンバー employee に代入する方法を示しています。

payroll.employee = number;

複合代入演算子は、両方のオペランドで演算を実行してから、その演算結果を 左辺オペランドに代入します。例えば、次の式は、index plus 2 の値を変数 index に代入します。

index += 2

Debug Tool は、tenary 演算子以外のすべての C 演算子をサポートし、また 他のすべての C 言語の代入、およびユーザー・ライブラリー または C ライブラリー関数への関数呼び出しをサポートします。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

C および C++ の %PATHCODE 値

下の表は、現行プログラム言語が C および C++ のときの、Debug Tool の 変数 %PATHCODE に使用可能な値を示しています。

-1 Debug Tool は、パスまたはアテンション状態の結果、制御をもっていません。
0 アテンション関数 (ATTENTION 条件ではありません)。
1 ブロックに入っています。
2 ブロックから出ようとしています。
3 制御がユーザー・ラベルに達しました。
4 関数参照の結果、制御が渡されています。呼び出されたルーチンのパラメーターがあれば、それは準備ができています。
5 関数参照から制御が戻されました。レジスター 15 に含まれる戻りコードはまだ記憶されていません。
6 条件ステートメントの do/whilefor、または while に含まれるロジックが実行されようとしています。これは、単一ステートメントかヌル・ステートメントであり、ブロック・ステートメントではありません。
7 if(...) に続くロジックが 実行されようとしています。
8 else に続くロジックが実行されようとしています。
9 switch 内の case に続くロジックが実行されようとしています。
10 switch 内のデフォルトに続くロジックが実行されようとしています。
13 switchdowhileif(...)、または for の終わりに続くロジックが実行されようとしています。
17 gotobreakcontinue、または return が実行されようとしています。

プログラムがパス・フックをサポートするオプションでコンパイルされた場合、3 から 17 の範囲内の値だけを %PATHCODE に割り当てることができます。

C および C++ でのセッション変数の宣言

セッション時に使用できるように、セッション変数を宣言してください。宣言でセッション変数を初期設定することはできません。ただし、セッション変数を初期設定するために、割り当てステートメントまたは関数呼び出しを使用することはできます。

C の場合と同様に、キーワードは任意の順序で指定することができます。変数名は、最高 255 文字の長さまで使用することができます。ID は、大文字と小文字の区別をしますが、現行のプログラム言語が C から 別の HLL に変更するときにセッション変数を使用したい場合には、変数は、大文字の名前および互換性 のある属性をもたなければなりません。

maximum という 16 進 浮動小数点変数を宣言するには、次の C 宣言を入力します。

double maximum;

Debug Tool では、スカラー、スカラーの配列、構造体、および共用体だけを 宣言することができます (これらに対するポインターも宣言することができます)。

プログラミング変数と同じ名前でセッション変数を宣言すると、セッション変数はプログラミング変数を隠します。プログラミング変数を参照するには、それを修飾しなければなりません。例えば、次のようになります。

main:>x for the program variable x
x for the session variable x

セッション変数は、CLEAR コマンドを使用してクリアしないかぎり、デバッグ・セッション全体にわたって有効です。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

C および C++ の式

Debug Tool では、テスト・プログラム内で式の計算を行うことができます。C および C++ で使用できるすべての式は、条件式 (? :) を除き、Debug Tool 内でも使用できます。すなわち、+-%:、および += などの演算子はすべて、完全にサポートされます (条件演算子は例外です)。

C および C++ 言語の式は、含まれる演算子とその使い方にもとづいて、次のようなグループに分類されます。

左辺値は、検査して変更できるデータ・オブジェクトを表す式です。式および演算子の詳しい説明は、C および C++ のプログラムの手引きを 参照してください。

C および C++ 演算子のセマンティクスは、コンパイルされた C または C++ プログラムの 場合と同じです。オペランドは、定数 (整数浮動小数点文字ストリング、および列挙型)、C および C++ 変数、Debug Tool 変数、または Debug Tool セッション時に宣言されたセッション変数を組み合わせて作ることができます。言語定数は、C および C++ の言語参照資料に説明されているとおりに 指定します。

Debug Tool コマンド DESCRIBE ATTRIBUTES を使用して、実際に式を計算しなくても、式の計算結果のタイプを表示することができます。

C および C++ 言語は、関数呼び出しの引数に対する計算順序は指定しません。したがって、式は、コンパイルされたコード内では、Debug Tool 内とは異なる実行 順序をもつことがあります。例えば、対話式セッションで次のように入力します。

int x;
int y;

x = y = 1;

printf ("%d %d %d%" x, y, x=y=0);

この場合、結果は、C または C++ プログラム・セグメント内にある同じステートメントによる結果とは異なる場合があります。ANSI 規格によって定義されていない動作を含む式は、Debug Tool が評価するとき、コンパイラーが評価するときとは異なった結果を出す場合があります。

次の例は、Debug Tool がプログラム内の式の使用をサポートするさまざまな 方法を示しています。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

Debug Tool からの C および C++ 関数の呼び出し

Debug Tool 内で、ユーザー・ライブラリー関数 および C ライブラリー関数への呼び出しを実行できます。ただし、ご使用のプログラムを DEBUG コンパイラー・オプションの FORMAT(DWARF) サブオプションを用いてコンパイルした場合は除きます。

C ライブラリー関数にはいつでも呼び出しを行うことができます。さらに、関数呼び出しを含む式で、C ライブラリー変数 stdinstdoutstderr__amrc、および errno を使用することができます。

ライブラリー関数 ctdli は、プログラム main あるいは main にリンクされた関数のどちらかにおいてコンパイル単位に参照が設定されていない場合は、呼び出すことができません。

ユーザー関数への呼び出しは、Debug Tool が、関数に関する必要な定義を ユーザー・プログラムのシンボル情報の中から探し出すことで きれば可能です。これらの定義は、プログラムが TEST(SYM) (C の 場合) または TEST (C++ の場合) を使用して コンパイルされる時に作成されます。

Debug Tool は、可能な場合、パラメーター変換およびパラメーター・ミスマッチ検査を 実行します。パラメーター検査は、次のような場合に実行されます。

SET WARNING OFF を指定することによって、この検査をオフにすることができます。

呼び出しは、C または C++ コンパイラーがリンケージを サポートしているユーザー関数であれば、どれに対しても行うことができます。ただし、C++ の場合、ユーザー関数を呼び出す場合は、関数を次のように宣言しておく必要があります。

extern "C"

例えば、アプリケーションのシグナル・ハンドラーを デバッグしたい場合にこの宣言を使用します。条件が発生すると、制御が Debug Tool に渡り、次にシグナル・ハンドラーに渡されます。

Debug Tool は、リンケージ検査を行って、リンケージのミスマッチがあると 判断した場合には、関数呼び出しを実行しません。リンケージのミスマッチは、ターゲット・プログラムにリンケージの指定があるが、ソース・プログラムには別のリンケージが指定されていると思われる場合に 発生します。

関数呼び出しに関しては次の点に注意することが大切です。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

C の予約済みキーワード

次の表に、C 言語によって予約済みのキーワードをすべて リストします。現行プログラム言語が C か C++ の場合、これらのキーワードを 省略して、変数名として使用したり、ほかのタイプの ID として使用したりすることはできません。

auto else long switch
break enum register typedef
case extern return union
char float short unsigned
const for signed void
continue goto sizeof volatile
default if static while
do int struct _Packed
double      

C 演算子およびオペランド

次の表には、C 言語演算子を優先順位に基づいてリストし、各演算子の 関連性の方向を示しています。1 次演算子が最も高い優先順位を持ちます。コンマ演算子が最も低い優先順位を持ちます。同じグループに属する演算子は、優先順位も同じです。

優先順位 関連性 演算子
1 次 左から右へ  ()  [ ]  .  ->
単項 右から左へ  ++  --  -  +  !   ~  &   *  (typename)  sizeof
乗除 左から右へ  *  /  %
加減 左から右へ  +  -
ビット単位のシフト 左から右へ  <<  >>
関係 左から右へ  <  >  <=  >=
等価 左から右へ  ++  !=
ビット単位の論理 AND 左から右へ  &
ビット単位の排他的 OR 左から右へ  ^ または ¬
ビット単位の包含 OR 左から右へ  |
論理 AND 左から右へ  &&
論理 OR 左から右へ  ||
代入 右から左へ  =  +=  -=  *=  /=   <<=  >>=  %=   &=  ^=   |=
コンマ 左から右へ  ,

言語環境プログラム条件および C/C++ の同等機能

言語環境プログラム条件名 (シンボリック・フィードバック・コード CEExxx) は、次の表 にリストされている同等機能の C および C++ 条件と、相互に置き換えることが 可能です。例えば、AT OCCURRENCE CEE341AT OCCURRENCE SIGILL と 同等です。CEE341 条件の発生で、AT OCCURRENCE SIGILL ブレークポイントが 起動され、その逆も成り立ちます。

言語環境プログラム条件 説明 同等の C/C++ 条件
CEE341 演算例外 SIGILL
CEE342 特権命令例外 SIGILL
CEE343 実行例外 SIGILL
CEE344 記憶保護例外 SIGSEGV
CEE345 アドレッシング例外 SIGSEGV
CEE346 指定例外 SIGILL
CEE347 データ例外 SIGFPE
CEE348 固定小数点オーバーフロー例外 SIGFPE
CEE349 固定小数点除算例外 SIGFPE
CEE34A 10 進オーバーフロー例外 SIGFPE
CEE34B 10 進除算例外 SIGFPE
CEE34C 指数オーバーフロー例外 SIGFPE
CEE34D 指数アンダーフロー例外 SIGFPE
CEE34E 有効数字例外 SIGFPE
CEE34F 浮動小数点除算例外 SIGFPE

Debug Tool による C および C++ の式の計算

Debug Tool は、ほとんどの入力を 1 つ以上の式の集まりとして解釈します。式を使用して、プログラム変数を変更したり、AT ブレークポイントが 制御しているポイントに式を追加してプログラムを拡張することができます。

Debug Tool は、C および C++ の式を「z/OS XL C/C++ ランゲージ・リファレンス」に示されている規則に従って評価します。式の計算の結果は、それと同じ式がコンパイルされたプログラムの 一部である場合の結果と同 じです。

暗黙のストリング連結がサポートされます。例えば、"abc" "def" は、"abcdef" として受け入れられ、同一のものとして扱われます。長いストリング・リテラルとストリング・リテラルの連結は、受け入れられません。例えば、L"abc"L"def" は有効であり、L"abcdef" と同値ですが、"abc" L"def" は無効です。

セッション時に使用する式は、式をコンパイルしたときの使用可能性と同じ センシティビティーで評価されます。使用可能になる条件は、プログラム・ステートメントについて存在する条件と 同じです。

Debug Tool のセッション時に、WARNING の現行の設定値が ON であれば、以下にリストしたいずれか 1 つの条件に当てはまる C または C++ プログラムが存在すると、診断メッセージが表示されます。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

C および C++ プログラムをデバッグするときのファイルのインターセプト

C アプリケーションのデバッグ時に、SET INTERCEPT コマンドを使用してファイルを代行受信 (インターセプト) する場合、いくつかの考慮事項に注意する必要があります。

CICS® の場合のみ: SET INTERCEPT は CICS ではサポートされません。

C++ の場合、入出力ストリームの代行受信に特定のサポートはありません。入出力ストリームは C I/O を使用してインプリメントされますが、その意味は次のとおりです。

注:
C/370™ I/O を経由して 間接的に入出力ストリームを代行受信することはできますが、その動作は C++ では異なる可能性があり、未定義です。

デバッグ・セッション中に、次の名前を SET INTERCEPT コマンドで 使用できます。

入出力インターセプトの動作は、system() 呼び出し境界を超える グローバルなものです。これは、プログラム A の中での INTERCEPT ON for xx の 設定は、プログラム B でも有効である (プログラム A が プログラム B に system() 呼び出しを行っている場合) ことを意味します。したがって、プログラム B がプログラム A に戻るようになっている場合には、プログラム B での xx に対する INTERCEPT OFF の設定は、プログラム A のインターセプトの設定をオフにします。この関係は、プログラム B でファイルをインターセプトし、プログラム B がプログラム A に戻る場合にも成り立ちます。このモデルは、ディスク・ファイル、メモリー・ファイル、および標準ストリームにも適用されます。

ストリームはインターセプトされると、fopen ステートメントで 指定された text/binary 属性を継承します。Debug Tool のログ・ファイルへの入出力は、端末入出力と同じように動作しますが、次のような考慮事項があります。

インターセプトされたファイルのそのほかの特性は、次のとおりです。

標準ストリームのコマンド行のリダイレクトは、Debug Tool のもとで次に 示すようにサポートされます。

1>&2
stderr がインターセプト・コマンドのターゲットである場合には、stdout もインターセプトされます。stdoutINTERCEPT コマンドのターゲットである場合には、stderr はインターセプトされません。INTERCEPTstdout について OFF にセットされていると、ストリームは stderr にリダイレクトされます。
2>&1
stdoutINTERCEPT コマンドのターゲットである場合には、stderr もインターセプトされます。stderrINTERCEPT コマンドのターゲットである場合には、stdout はインターセプトされません。INTERCEPTstderr について OFF にセットされていると、ストリームは再び stdout にリダイレクトされます。
1>file.name
stdout は、file.name にリダイレクトされます。stdout のインターセプトが発生する場合には、stdout また は file.name をインターセプト要求で指定することができます。これは 1>>file.name にも適用されます。
2>file.name
stderr は、file.name にリダイレクトされます。stderr のインターセプトが発生する場合には、stderr または file.name をインターセプト要求で指定することができます。これは 2>>file.name にも適用されます。
2>&1 1>file.name
stderr は、stdout にリダイレクトされ、両方とも file.name にリダイレクトされます。file.name をインターセプト・コマンドで指定すると、stderrstdout の両方がインターセプトされます。stderr または stdoutINTERCEPT コマンドで指定すると、その動作は上記の規則 1b に従います。
1>&2 2>file.name
stdoutstderr にリダイレクトされて、その両方とも file.name にリダイレクトされます。file.nameINTERCEPT コマンドで指定すると、stderrstdout の両方がインターセプトされます。stdout または stderrINTERCEPT コマンドで指定すると、その動作は上記の規則 1a に従います。

同じ標準ストリームを二度コマンド行でリダイレクトすることはできません。次に示すように、インターセプトはこの規則が違反されると定義されません。

2>&1 2>file.name
stderr の動作は定義されません。
1>&2 1>file.name
stdout の動作は定義されません。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

C および C++ のオブジェクトの有効範囲

オブジェクトは、そのデータ・タイプおよび宣言された名前がブロックまたは ソース・ファイルの中で認識されれば、そのブロックまたはソース・ファイル内で可視 になります。オブジェクトが可視である領域は、その有効範囲として呼ばれます。Debug Tool では、変数または関数をオブジェクトにすることができ、また 行番号の参照にも使用します。

注:
この場合のオブジェクトの使用を C++ のオブジェクトと混同しないでください。すべての C++ への参照は、そのように修飾されます。

ANSI C では、次の 4 つの種類の有効範囲があります。

C++ の場合、C に対して定義された有効範囲に加えて、クラス有効範囲もあります。

オブジェクトは、その宣言がブロック内部にあれば、ブロック有効範囲を もちます。ブロック有効範囲をもつオブジェクトは、宣言されている点からブロックを 終了する右中括弧 (}) までが可視領域です。

オブジェクトの定義が任意のブロック外部にあれば、そのオブジェクトは ファイル有効範囲をもちます。ファイル有効範囲をもつオブジェクトは、その宣言の場所からソース・ファイルの 終わりまでが、可視領域になります。Debug Tool では、コンパイル単位をファイルの静的変数で修飾すると、ファイル静的変数およびグローバル変数は常に可視的なものです。

関数有効範囲をもつオブジェクトの唯一のタイプは、ラベル名です。

オブジェクトの宣言が関数のプロトタイプのパラメーター・リスト内にあれば、そのオブジェクトは関数のプロトタイプ有効範囲をもちます。

クラス・メンバーは、その宣言がクラス内にある場合は、クラス有効範囲をもちます。

関数のプロトタイプ有効範囲で可視オブジェクトを 参照することはできませんが、次のような場合には、ファイル有効範囲または ブロック有効範囲で可視オブジェクトは参照できます。

Debug Tool は、ANSI と同じ有効範囲の規則に従いますが、ファイル有効範囲ではオブジェクトの扱い方が異なります。ファイル有効範囲のオブジェクトは、ソース・ファイル内のそれが宣言されている 場所からだけでなく、ソース・ファイル内の任意の場所で Debug Tool の中から 参照できます。Debug Tool のセッション変数は、常にプログラム変数よりも高い有効範囲をもつので、同じ名前をもつプログラム変数よりも高い優先順位をもちます。プログラム変数は、常に修飾を介してアクセスできます。

さらに、Debug Tool は複数のロード・モジュールにある変数の参照を サポートします。複数のロード・モジュールは、C ライブラリー関数 dllload()dllfree()fetch()、および release() を介して管理されます。

例: C および C++ ブロックでの変数の参照とブレークポイントの設定

C および C++ のストレージ・クラス

Debug Tool は、次のストレージ・クラスを使用して宣言されたすべてのオブジェクトの 変更および参照をサポートします。

Debug Tool セッション中に宣言されたセッション変数は、参照および変更用に 使用することもできます。

auto ストレージ・クラスをもつオブジェクトは、その中で オブジェクトが定義されたブロックが活動状態であれば、Debug Tool で 参照または変更用に使用できます。一度ブロックが実行を終了すると、このブロック内の auto 変数は、変更には使用できなくなりますが、DESCRIBE ATTRIBUTES を使用して検査することは可能です。

register ストレージ・クラスのオブジェクトは、変数がレジスターに 対して最適化されていなければ、Debug Tool で参照または変更に使用できる場合が あります。

static ストレージ・クラスのオブジェクトは、常に Debug Tool で変更または 参照に使用できます。現在修飾されているコンパイル単位にない場合には、それを明確に 修飾しなければなりません。

extern ストレージ・クラスのオブジェクトは、常に Debug Tool で変更または 参照に使用できます。また、プログラム内の変数などは、このソース・ファイルの中で定義または 参照されなくても、参照することができます。これは、Debug Tool が別のコンパイル単位 (TEST(SYM) を使用して コンパイルされたもの) を、適切な定義で探すことができる場合に可能です。

C の場合のブロックおよびブロック ID

あるブロックへの入口、またはそのブロックからの出口にブレークポイントを 設定したり、現行ブロックから直接には見えない変数を参照する必要がある ことがしばしばあります。すべてのブロックに名前が付けられていれば、Debug Tool はこれを行えます。Debug Tool は、次の命名規則を使用します。

これらのブロック名が Debug Tool コマンドで使用されると、同じソース・ファイルの異なる 関数内でネストされたブロック同士を区別する必要があります。そのためには次の 2 つの方法のいずれかを使用してブロックに名前を付けます。

短い形式
function_name:>%BLOCKzzz
長い形式
function_name:>%BLOCKxxx :>%BLOCKyyy: ... :>%BLOCKzzz

%BLOCKzzz%BLOCKyyy の中に含まれ、%BLOCKyyy%BLOCKxxx の中に含まれます。短い形式が常に使用できますから、長い形式での指定は必ずしも 必要ではありません。

現在活動状態のブロック名は、Debug Tool 変数 %BLOCK から 検索することができます。次のように入力して、ブロックの名前を表示することができます。

DESCRIBE CU;

C++ の場合のブロックおよびブロック ID

C++ の場合、ブロック ID が C の場合よりも長くなりがちである理由は、C++ の関数は多重定義できるからです。ある関数名を他の関数名と区別するために、それぞれのブロック ID は プロトタイプと同じ意味をもちます。例えば、C で shapes(int,int) の名前をもつ関数は、shapes という名のブロックをもちますが、C++ では ブロック名は shapes(int,int) となります。

C++ のブロックは、関数が多重定義されていなくても、ブロック全体の ID を指す必要があります。すなわち、shapes(int,int) の参照は、shapes のみではできません。

注:
main() のブロック名は常に main (後ろに修飾パラメーターはつけない) であり、C++ でコンパイルしてもそうです。なぜなら、main()C に外部リンケージを持つからです。

ブロック名を相当に長くすることができるため、画面の 1 行目の LOCATION フィールドで、名前 が切り捨てられて表示されることはまれではありません。位置を正確に知る必要がある場合は、次のように入力します。

QUERY LOCATION

名前の全体がセッション・ログに表示されます (行を折り返して)。

ブロック ID の長さは 255 文字までの制限があります。255 文字以上の名前は切り捨てられます。

例: C および C++ ブロックでの変数の参照とブレークポイントの設定

次のプログラムはいくつかのプログラムの基本として使用されます。これに ついてはプログラム・リストの後に説明します。

#pragma runopts(EXECOPS)
#include <stdlib.h>

main()
{
      >>> Debug Tool is given <<<
      >>> control here.    <<<
  init();
  sort();
}

short length = 40;
static long *table;

init()
{
  table = malloc(sizeof(long)*length);

  ·
  ·
  ·
} sort () { /* Block sort */ int i; for (i = 0; i < length-1; i++) { /* If compiled with ISD, Block %BLOCK2; */ /* if compiled with DWARF, Block %BLOCK8 */ int j; for (j = i+1; j < length; j++) { /* If compiled with ISD, Block %BLOCK3; */ /* if compiled with DWARF, Block %BLOCK13 */ static int temp; temp = table[i]; table[i] = table[j]; table[j] = temp; } } }

C および C++ プログラムでのオブジェクトの有効範囲と可視性

上記に示すプログラムが TEST(SYM) でコンパイルされているとします。Debug Tool が制御を受け取ると、ファイル有効範囲変数 length および table は次のように変更が可能です。

length = 60;

ブロック有効範囲変数 ij、および temp はこの有効範囲では可視ではなく、この時点では Debug Tool の中から直接参照することはできません。次のコマンドを入力して、現在の有効範囲内の行番号をリストできます。

LIST LINE NUMBERS;

このプログラムが TEST(SYM, NOBLOCK) でコンパイルされているとします。プログラムが NOBLOCK を使用して明示的にコンパイルされると、変数 j および temp は別のブロックで ネストされたブロックで定義されているので、Debug Tool がこれらの変数を認識することはできません。Debug Tool は、変数 i がネストされた有効範囲内に ないので、これを認識します。

C および C++ プログラムでのブロックおよびブロック ID

上記のプログラムでは、関数 sort には以下の 3 つの ブロックがあります。

プログラムが、ISD コンパイラー・オプションでコンパイルされる場合 プログラムが、DWARF コンパイラー・オプションでコンパイルされる場合
sort sort
%BLOCK2 %BLOCK8
%BLOCK3 %BLOCK13

次のようにして、入り口のブレークポイントを sort の 2 番目のブロックにセットします。

次の例は、main の最初のブロックの出口にブレークポイントをセットして、ソートされたテーブルの項目をリストします。

at exit main {
  for (i = 0; i < length; i++)
    printf("table entry %d is %d¥n", i, table[i]);
}

次の例は、sort の 3 番目のブロック内の変数 temp をリストします。これは、tempstatic ストレージ・クラスを持つので可能です。

C および C++ プログラム用の環境情報の表示

DESCRIBE コマンドを使用して、現行のランタイム環境に該当する属性のリストを表示することもできます。表示される情報のタイプは、言語によって異なります。

DESCRIBE ENVIRONMENT を発行すると、ランタイム環境によりモニターされているオープン・ファイルと条件のリストが表示されます。例えば、C または C++ プログラム のデバッグ中に DESCRIBE ENVIRONMENT を入力すると、次のような出力が得られます。

Currently open files
    stdout
    sysprint
The following conditions are enabled:
    SIGFPE
    SIGILL
    SIGSEGV
    SIGTERM
    SIGINT
    SIGABRT
    SIGUSR1
    SIGUSR2
    SIGABND

C および C++ での変数の修飾と視点の変更

修飾は、次のことを行うための方法です。

名前が競合する場合、またはプログラムが複数のロード・モジュール、コンパイル単位または関数 (あるいはその両方) で構成されているときに、修飾が必要になります。

プログラムの実行が中断され、Debug Tool が制御を受け取ると、デフォルトの修飾、すなわち暗黙の 修飾が、プログラムの中断した場所での 活動ブロックになります。このブロック内の C または C++ プログラムにとって可視的である すべてのオブジェクトは、Debug Tool にとっても可視的です。このようなオブジェクトは、修飾子を使用せずにコマンドで 指定することができます。それ以外はすべて、明示修飾 を使用して指定されなければなりません。

修飾子は、作業しているシステムの命名規則に当然従います。

例: C の場合の修飾子の使用

C および C++ での変数の修飾

次のことに考慮して、オブジェクトを正確に指定することができます。

これらは修飾子として認識され、その一部またはすべては、オブジェクトをコマンドで参照するときに必須です。修飾子は、より大きい記号 (>) とコロンの組み合わせで区切り、その後に修飾するオブジェクトを置きます。例えば、次は、完全修飾のオブジェクトです。

load_name::>cu_name:>block_name:>object

必要であれば、load_name がロード・モジュールの名前となります。ロード・モジュールの名前は、プログラムが複数のロード・モジュールで 構成される場合で、かつ修飾を現行のロード・モジュール以外に変更したい 場合にのみ必要です。load_name は二重引用符 (") で囲みます。 そうでない場合は、C または C++ プログラム言語で有効な識別名で なければなりません。load_name は、Debug Tool 変数の %LOAD にすることもできます。

必要であれば、CU_NAME がコンパイル単位または ソース・ファイルの名前となります。cu_name は、完全に修飾されたソース・ファイル名であるか、または絶対パス名でなければなりません。この指定は、現在修飾しているコンパイル単位以外に修飾を変更したい 場合にのみ必要です。これは、Debug Tool 変数 %CU にすることができます。コンパイル単位名と (例えば) ブロック名との間があいまいである場合には、コンパイル単位名を引用符 (") で囲まなければなりません。

必要であれば、block_name がブロックの名前となります。block_name は、Debug Tool 変数の %BLOCK にすることができます。

例: C の場合の修飾子の使用

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

C および C++ での視点の変更

コマンド行またはコマンド・ファイルから視点を変更するには、修飾子を SET QUALIFY コマンドで使用してください。この方法は、現行の視点からはアクセスできないデータを獲得するのに 必要であり、多くの オブジェクトが参照されるときのデバッグ操作を 簡単にすることができます。

視点を別のロード・モジュールや DLL、別のコンパイル単位、ネストされたブロック、またはネストされていないブロックに変更することができます。SET キーワードはオプションです。

例: C の場合の修飾子の使用

例: C の場合の修飾子の使用

下記の例では次のプログラムを使用します。

LOAD MODULE NAME:  MAINMOD
SOURCE FILE  NAME:  MVSID.SORTMAIN.C

short length = 40;
main ()
{
  long *table;
  void (*pf)();

  table = malloc(sizeof(long)*length);

  ·
  ·
  ·
pf = fetch("SORTMOD"); (*pf)(table);
  ·
  ·
  ·
release(pf);
  ·
  ·
  ·
} LOAD MODULE NAME: SORTMOD SOURCE FILE NAME: MVSID.SORTSUB.C short length = 40; short sn = 3; void (long table[]) { short i; for (i = 0; i < length-1; i++) { short j; for (j = i+1; j < length; j++) { float sn = 3.0; short temp; temp = table[i];
  ·
  ·
  ·
>>> Debug Tool is given <<< >>> control here. <<<
  ·
  ·
  ·
table[i] = table[j]; table[j] = temp; } } }

Debug Tool が制御を得ると、変数 ijtemptable、および length は、修飾子なしでコマンドに指定できます。変数 sn が参照される場合、Debug Tool は float である 変数を使用します。ただし、ブロックとコンパイル単位の名前は異なり、オペレーティング・システムとの互換性を維持します。

C での変数の修飾

C での視点の変更

C++ プログラムのステップスルー

オブジェクトを生成 (construct) および消去 (destruct) しながら、メソッドをステップスルーできます。さらに、静的なコンストラクター (生成関数) とデストラクター (消去関数) を ステップスルーすることができます。これらはそれぞれ、main() の前と後に実行されるオブジェクトのメソッドです。

ヘッダー・ファイルにある関数を呼び出すプログラムをデバッグする場合、カーソルはアプリケーションのヘッダー・ファイルに移動します。そうすると、関数のソースをステップスルーするとき、それを見ることができます。関数から戻った後は、関数を呼び出した元の場所に続く行から デバッグが続行します。

また、STEP OVER コマンドにより、ヘッダー・ファイル関数を飛ばしてステップを進めることもできます。これは、自分ではデバッグができないライブラリー関数 (例: string.h に定義されたストリング関数) をステップオーバーする ときに便利です。

C++ でのブレークポイントの設定

C++ と C でのブレークポイントの設定の違いについて、次に説明します。

AT ENTRY/EXIT を使用する C++ でのブレークポイントの設定

AT ENTRY/EXIT は、指定されたブロックにブレークポイントをセットします。メソッド、ネストされたクラスの中のメソッド、テンプレート、多重定義の演算子に対してブレークポイントの設定ができます。それぞれの例を下に示します。

ブロック ID は非常に長くなることがあり、特に、テンプレート、ネストされたクラス、多段階の継承をもつクラスでは長くなります。実際、特定の関数に対応するブロック名は、最初明確に分からない場合さえあります。これらの重要なブロックにブレークポイントをセットするのは、非常に面倒でもあります。したがって、DESCRIBE CU を使用 して、セッション・ログからブロック ID を検索することを お勧めします。

DESCRIBE CU を実行すると、常にクラスで修飾されたメソッドが 表示されます。メソッドが固有の場合には、メソッド名だけの使用でブレークポイントの設定が可能です。メソッドが固有でない場合には、メソッドをクラス名で修飾することが必要です。次の 2 つの例は同等です。

AT ENTRY method()

AT ENTRY classname::method()

次の例は有効です。

AT ENTRY square(int,int) 「単純」メソッド square
AT ENTRY shapes::square(int) メソッド square はそのクラス shapes により修飾されます。
AT EXIT outer::inner::func() ネストされたクラス。outer と inner はクラスです。func() はクラス inner の中にあります。
AT EXIT Stack<int,5>::Stack() テンプレート。
AT ENTRY Plus::operator++(int) 多重定義演算子。
AT ENTRY ::fail() ファイル有効範囲で定義された関数は、グローバル有効範囲演算子 :: により参照する必要があります。

次の例は無効です。

AT ENTRY shapes ここで、shapes はクラスです。クラスにブレークポイントをセットすることはできません。(クラスにはブロック ID がありません。)
AT ENTRY shapes::square メソッド square の後にはパラメーター・リストが必要なので、無効です。
AT ENTRY shapes:>square(int) shapes が、ブロック名ではなくクラス名なので無効です。

AT CALL を使用する C++ でのブレークポイントの設定

AT CALL は、アプリケーション・コードが指定の入り口点を 呼び出そうとしたときに、Debug Tool に制御を与えます。入り口名は、完全修飾名である必要があります。すなわち、DESCRIBE CU で示される名前を使用する必要があります。次の例、

AT ENTRY shapes::square(int)

を使用し、メソッド square にブレークポイントをセットするには、次を入力する必要があります。

AT CALL shapes::square(int)

square が固有のものとして識別可能であっても、この形の指定が必要です。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

C++ オブジェクトを調べる場合

C++ オブジェクトを表示する場合、ローカル・メンバー変数のみが表示されます。アクセス・タイプ (public、private、protected) は、変数間で区別されません。メンバーの関数は表示されません。メンバーの関数の属性を見たい場合は、個々には表示できますが、クラスと 関連付けての表示はできません。派生クラスを表示する場合、その中にある基底クラスがタイプ・クラスとして 表示され、拡張されません。

ここで述べた内容に関して詳しくは、以下のトピックを参照してください。

例: C++ オブジェクトの属性の表示

下記の例では次の定義を使用します。

class shape { ... };

class line : public shape {
  member variables of class line...
}

line edge;

C++ オプジェクトのオブジェクト属性の表示

オブジェクト edge の属性を記述するには、次のコマンドを 入力します。

DESCRIBE ATTRIBUTES edge;

ログ・ウィンドウには次の出力が表示されます。

DESCRIBE ATTRIBUTES edge;
ATTRIBUTES for edge
  Its address is yyyyyyyy and its length is xx
  class line
     class shape
     member variables of class shape....

基底クラスは、クラス shape _shape として表示されていることに 注意してください。

C++ でのクラス属性の表示

クラス shape の属性を表示するには、次のコマンドを 入力します。

DESCRIBE ATTRIBUTES class shape;

ログ・ウィンドウには次の出力が表示されます。

DESCRIBE ATTRIBUTES class shape ;
 ATTRIBUTES for class shape
   const class shape...

C++ での静的データの表示

クラスに静的データが含まれる場合、その静的データは クラスの一部として表示されます。例えば、次のようになります。

class A {
  int x;
  static int y;
}

A obj;

クラス A の各オブジェクトは同じ値を持つため、A::y として静的メンバーを参照し、静的メンバーを表示することもできます。

C++ でのグローバル・データの表示

あいまいさを避けるために、ファイル有効範囲で宣言した変数の参照には、グローバル有効範囲演算子 :: の使用が可能です。例えば、次のようになります。

int x;
class A {
   int x;

  ·
  ·
  ·
} }

A のメンバー関数のなかにいるときに、ファイル有効範囲で x の値を 表示したい場合は、LIST ::x と入力します。:: を使用せずに、LIST x を入力すると、現行オブジェクトの x の値 (すなわち、this->x) を表示します。

C++ のストレージのモニター

LIST REGISTERS コマンドを使用して、コードとアセンブリー・リストをステップごとに進めながら、レジスター (汎用および浮動小数点) をモニターすると便利な場合があります。コンパイラー・リストは、Debug Tool のフックを含め、疑似アセンブリー・コードを表示しています。停止する場所のフックを見たり、フックの間の疑似アセンブリー命令にしたがって、レジスター内の値が予期したとおりに 変わっていくのを段階的に監視することができます。また、コードをステップごとに進めながら、マシン・レジスターの 値を変更することもできます。

ストレージの内容はさまざまな方法でリストすることができます。LIST REGISTERS コマンドを使用すると、汎用レジスターまたは浮動小数点レジスターの内容のリストを得ることができます。

ストレージのダンプ形式の表示を指定して、ストレージの内容を モニターすることもできます。これを行うには、LIST STORAGE コマンドを使用します。表示したいストレージのアドレス、およびバイト数を指定することができます。

例: C におけるレジスターおよびストレージのモニターと変更

下記の例では、次の C プログラムを使用してレジスターとストレージの モニターと変更の方法を示しています。

int dbl(int j)            /* line 1 */
{                         /* line 2 */
  return 2*j;             /* line 3 */
}                         /* line 4 */
int main(void)
{
  int i;
  i = 10;
  return dbl(i);
}

コンパイラー・オプション TEST(ALL),LIST を使用して上記のプログラムをコンパイルすると、疑似アセンブリー・リストは下記に示すようなものになります。

*  int dbl(int j)
           ST    r1,152(,r13)
*  {
           EX    r0,HOOK..PGM-ENTRY
*    return 2*j;
           EX    r0,HOOK..STMT
           L     r15,152(,r13)
           L     r15,0(,r15)
           SLL   r15,1
           B     @5L2
           DC    A@5L2-ep)
           NOPR
 @5L1      DS    0D
*  }
 @5L2      DS    0D
           EX    r0,HOOK..PGM-EXIT

モニター・ウィンドウに、更新されたレジスターを継続的に 表示するには、次のコマンドを入力します。

MONITOR LIST REGISTERS

少しステップを進めた後、Debug Tool は行 1 (上記のリスト に示すプログラム入り口フック) で停止します。ここで STEP すると、行 3 に進み、ステートメント・フック で停止します。次に STEP すると、行 4 に進み、プログラム出口フックで 停止します。疑似アセンブリー・リストが示すように、この STEP 処理の 間、レジスター 15 だけが変更され、ここには関数の戻り値が 含まれることがわかります。モニター・ウィンドウ には、レジスター 15 に予想した値 0x00000014 (10 進数の 20) が 表示されています。

次のコマンドを出して、dbl() から戻る直前に、値を 20 から 8 に変更することができます。

%GPR15 = 8 ;

ご利用条件 | フィードバック

このインフォメーション・センターでは Eclipse テクノロジーが採用されています。(http://www.eclipse.org)