ゼロ除算のエラー
図 1 に、ゼロ除算のエラーが発生した C プログラムを示します。コード は RENT でコンパイルされたので、WSA フィールドから静的変数 および外部変数を計算する必要があります。関数およびデータのアドレスの計算に使用するリストを生成する ために、コードは XREF、LIST、および OFFSET で コンパイルされました。次に、バインダー・マップを生成するために、コードは MAP を使用してバインダーにより処理されました。このバインダー・マップは、静的変数および外部変数のアドレスを 計算するために使用されます。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int statint = 73;
int fa;
void funcb(int *pp);
int main(void) {
int aa, bb=1;
aa = bb;
funcb(&aa);
return(99);
}
void funcb(int *pp) {
int result;
fa = *pp;
result = fa/(statint-73);
return;
}
このルーチンをデバッグするには、次のステップに従ってくださ い。
- ダンプにおけるアクティブ・ルーチンの条件情報のセクション内で元の条件メッセージを見つ
けてくだ
さい。この例では、メッセージは CEE3209S です。 システムは固定-小数点除算例外を検出しました。
このメッセージは、ゼロ除算を実行しようとしたためにエラーが発生
したことを示します。CEE3209S についての詳細は、「z/OS Language Environment ランタイム・メッセージ」を参照してください。
ダンプのトレースバック・セクションは、関数 funcb 内のオフセット X'76' で例外が発生したことを示しています。 この情報をコンパイラー生成の疑似アセンブリー・リストと共に使用して、問題が発生した場所を判別します。
TEST コンパイラー・オプションを指定した場合には、 変数情報がダンプに組み込まれます。 GONUMBER コンパイラー・ オプションを指定した場合には、ステー トメント番号情報がダンプに組み込まれます。図 2 にダンプから生成されたトレースバックを示します。
図 2. C/C++ ルーチン例 (ゼロ除算エラー) から生成されたダンプのセクションCEE3DMP V1 R12.0: Condition processing resulted in the unhandled condition. 05/24/10 6:20:36 PM Page: 1 ASID: 0049 Job ID: JOB23480 Job name: CDIVZERO Step name: STEP1 UserID: HEALY CEE3845I CEEDUMP Processing started. Information for enclave main Information for thread 8000000000000000 Traceback: DSA Entry E Offset Statement Load Mod Program Unit Service Status 1 CEEHDSP +00004030 CEEPLPKA CEEHDSP D1908 Call 2 funcb +00000076 18 CDIVZERO Exception 3 main +00000064 12 CDIVZERO Call 4 EDCZMINV +000000C2 CEEEV003 Call 5 CEEBBEXT +000001B6 CEEPLPKA CEEBBEXT D1908 Call DSA DSA Addr E Addr PU Addr PU Offset Comp Date Compile Attributes 1 20FCB358 209C4238 209C4238 +00004030 20061215 CEL 2 20FCB2B0 20900960 20900960 +00000076 20070115 C/C++ 3 20FCB208 209008E0 209008E0 +00000064 20070115 C/C++ 4 20FCB0F0 20E699EE 20E699EE +000000C2 20061215 LIBRARY 5 20FCB030 20992208 20992208 +000001B6 20061215 CEL Condition Information for Active Routines Condition Information for (DSA address 20FCB2B0) CIB Address: 20FCBC78 Current Condition: CEE0198S The termination of a thread was signaled due to an unhandled condition. Original Condition: CEE3209S The system detected a fixed-point divide exception (System Completion Code=0C9). Location: Program Unit: Entry: funcb Statement: 18 Offset: +00000076 Machine State: ILC..... 0002 Interruption Code..... 0009 PSW..... 078D2400 A09009D8 GPR0..... 00000000_20900A08 GPR1..... 00000000_00000000 GPR2..... 00000000_20FCB2A8 GPR3..... 00000000_2090099A GPR4..... 00000000_00000000 GPR5..... 00000000_00000001 GPR6..... 00000000_20900B24 GPR7..... 00000000_20900098 GPR8..... 00000000_00000030 GPR9..... 00000000_80000000 GPR10.... 00000000_A0E699E2 GPR11.... 00000000_A0992208 GPR12.... 00000000_209139B0 GPR13.... 00000000_20FCB2B0 GPR14.... 00000000_20914F50 GPR15.... 00000000_00000008 Storage dump near condition, beginning at location: 209009C6 +000000 209009C6 5811E000 504FE000 A71AFFB7 8E400020 1D4158F0 306A4110 D0985000 D0985050 |....&|..x.... .....0.....q&..q&&| GPREG STORAGE: Storage around GPR0 (20900A08) -0020 209009E8 0DEF18F5 58D0D004 58E0D00C 9825D01C 051E0707 00000000 00000008 209000B8 |...5........q...................| +0000 20900A08 D985A2A4 93A3407E 406C8415 00000000 1CCEA106 00000228 00000178 00000000 |Result = %d.....................| ⋮
- 図 3 の疑似アセンブリー・リストで、ゼロ除算のエラーが発生した命令を見つけます。
トレースバック (X'76') からの例外のオフセット (funcb 内) は、その位置にある除算命令 DR r4,r1 を示しています。命令 X'66' から X'76' は、C/C++ ルーチンの result = fa/(statint-73); 行を参照します。
図 3. 疑似アセンブリー・リスト (C/C++ ルーチンのゼロ除算エラー)OFFSET OBJECT CODE LINE# FILE# P S E U D O A S S E M B L Y L I S T I N G 000015 | * int funcb(int *pp) { 000000 000015 | funcb DS 0D . . . 000046 50D0 E004 000015 | ST r13,4(,r14) 00004A 18DE 000015 | LR r13,r14 00004C End of Prolog 00004C 58E0 C1F4 000000 | L r14,_CEECAA_(,r12,500) 000016 | * int result; 000017 | * fa = *pp; 000050 5820 1000 000017 | L r2,pp(,r1,0) 000054 5810 3062 000018 | L r1,=Q(statint)(,r3,98) 000058 58F0 3066 000017 | L r15,=Q(fa)(,r3,102) 00005C C000 0000 0026 000000 | LARL r0,F'38' 000062 5840 2000 000017 | L r4,(*)int(,r2,0) 000018 | * result = fa/(statint-73); 000066 5811 E000 000018 | L r1,statint(r1,r14,0) 00006A 504F E000 000017 | ST r4,fa(r15,r14,0) 00006E A71A FFB7 000018 | AHI r1,H'-73' 000072 8E40 0020 000018 | SRDA r4,32 000076 1D41 000018 | DR r4,r1 000019 | * printf("Result = %d\n",result); 000078 58F0 306A 000019 | L r15,=V(printf)(,r3,106) 00007C 4110 D098 000019 | LA r1,#MX_TEMP2(,r13,152) 000080 5000 D098 000019 | ST r0,#MX_TEMP2(,r13,152) 000084 5050 D09C 000019 | ST r5,#MX_TEMP2(,r13,156) 000088 0DEF 000019 | BASR r14,r15 000020 | * return result; 00008A 18F5 000020 | LR r15,r5 000021 | * } 00008C 000021 | @2L3 DS 0H 00008C Start of Epilog 00008C 58D0 D004 000021 | L r13,4(,r13) 000090 58E0 D00C 000021 | L r14,12(,r13) 000094 9825 D01C 000021 | LM r2,r5,28(r13) 000098 051E 000021 | BALR r1,r14 00009A 0707 000021 | NOPR 7 00009C Start of Literals 00009C 00000000 =Q(statint) 0000A0 00000000 =Q(fa) 0000A4 00000000 =V(printf) 0000A8 End of Literals *** General purpose registers used: 1111110000001111 *** Floating point registers used: 1111111100000000 *** Size of register spill area: 128(max) 0(used) *** Size of dynamic storage: 168 *** Size of executable code: 156 Constant Area 000000 D985A2A4 93A3407E 406C8415 00 |Result = %d.. | PPA1: Entry Point Constants 000000 1CCEA106 =F'483303686' Flags 000004 00000228 =A(PPA2-main) 000008 00000178 =A(PPA3-main) 00000C 00000000 =F'0' No EPD 000010 FE000000 =F'-33554432' Register save mask 000014 00000000 =F'0' Member flags 000018 90 =AL1(144) Flags 000019 000000 =AL3(0) Callee's DSA use/8 00001C 0040 =H'64' Flags 00001E 0012 =H'18' Offset/2 to CDL 000020 00000000 =F'0' Reserved 000024 5000003C =F'1342177340' CDL function length/2 000028 FFFFFEC8 =F'-312' CDL function EP offset 00002C 38260000 =F'942014464' CDL prolog 000030 40090033 =F'1074331699' CDL epilog 000034 00000000 =F'0' CDL end 000038 0004 **** AL2(4),C'main' PPA1 End ⋮
- 除数 statint の値を調べます。以下に示す手順は、静的変数の値の判別のみに使用します。除数が自動変数である場合は、変数の値を探す手順が異なります。ダンプで自動変数を探す方法の詳細については、自動変数検索のステップを参照してください。
このルーチンは RENT オプションを指定してコンパイルされたので、ダンプのエンクレーブ制御ブロック・セクションで WSA アドレスを探します。この例では、アドレスは X'20914F50' です。図 4 に WSA アドレスを示します。
図 4. ダンプの C/C++ CAA 情報 (C/C++ ルーチンのゼロ除算エラー)Enclave Control Blocks: ⋮ WSA address.................20914F50 ⋮
- RENT オプションを指定してコンパイルしたルーチンは、バインダーによる処理を行う必要があります。バインダーにより、書き込み可能静的マップが生成されます。
図 5 の
書き込み可能静的マップで、statint のオフセットを探します。この例では、オフセットは X'0' です。図 5. 書き込み可能静的マップ (C/C++ ルーチンのゼロ除算エラー)
⋮ --------------- CLASS C_WSA LENGTH = AC ATTRIBUTES = MRG, DEFER , RMODE=ANY OFFSET = 0 IN SEGMENT 002 ALIGN = DBLWORD --------------- CLASS OFFSET NAME TYPE LENGTH SECTION 0 statint PART 4 statint 8 fa PART 4 fa 10 environ PART 4 environ 18 errno PART 4 errno ⋮
- WSA アドレス X'20914F50' を statint のオフセットに加算します。その結果、X'20914F50' になります。これは、書き込み可能静的域にある変数 statint のアドレスです。
書き込み可能静的域は、ダンプのエンクレーブ・ストレージのセクションに 表示されます。ロード・モジュールの場合、書き込み可能静的域は、C/C++ ランタイム環境により C/C++ ユーザー用に割り振られたストレージなので、ユーザー・ヒープ内に入っています。プログラム・オブジェクトでは、書き込み可能静的域はローダーによって割り振られたストレージで、ダンプのプログラム・オブジェクト用 WSA のセクションに示されています。
この例では、プログラムはプログラム・オブジェクトとしてビルドされています。 書き込み可能静的域は、ダンプのエンクレーブ・ストレージのセクション (図 6 を参照) に 表示されます。
- 書き込み可能静的域内の変数 statint を探すためには、出力されているうちで 最も近いアドレス (statint のアドレスより前) を探してください。この場合、アドレスは X'20914F50' です。そこから X'00' 進むと、X'20914F50' の位置です。その位置の値は X'49' (つまり statint は 73) であり、固定小数点除算例外となります。
Enclave Storage:
⋮
WSA for Program Object(s)
WSA: 20914F50
+000000 20914F50 00000049 00000000 00000001 00000000 2090A880 00000000 00000000 00000000 |..................y.............|
+000020 20914F70 20910260 2091026A 00000000 00000000 00000000 00000000 00000000 00000000 |.j.-.j..........................|
+000040 20914F90 00000001 00000000 00000001 00000000 00000000 00000000 00000000 00000000 |................................|
+000060 20914FB0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................|
+000080 20914FD0 00000000 00000000 00000000 00000000 2090F6BC 00000000 2090F28C 00000000 |..................6.......2.....|
+0000A0 20914FF0 2090F4A4 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |..4u............................|
⋮