ゼロ除算のエラー

図 1 に、ゼロ除算のエラーが発生した C プログラムを示します。コード は RENT でコンパイルされたので、WSA フィールドから静的変数 および外部変数を計算する必要があります。関数およびデータのアドレスの計算に使用するリストを生成する ために、コードは XREF、LIST、および OFFSET で コンパイルされました。次に、バインダー・マップを生成するために、コードは MAP を使用してバインダーにより処理されました。このバインダー・マップは、静的変数および外部変数のアドレスを 計算するために使用されます。

図 1. ゼロ除算のエラーが発生した C ルーチン
#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;
}

このルーチンをデバッグするには、次のステップに従ってくださ い。

  1. ダンプにおけるアクティブ・ルーチンの条件情報のセクション内で元の条件メッセージを見つ けてくだ さい。この例では、メッセージは 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.....................|
    
    ⋮
  2. 図 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                                                                                                  
    ⋮                                                                                                                                   
  3. 除数 statint の値を調べます。以下に示す手順は、静的変数の値の判別のみに使用します。除数が自動変数である場合は、変数の値を探す手順が異なります。ダンプで自動変数を探す方法の詳細については、自動変数検索のステップを参照してください。

    このルーチンは RENT オプションを指定してコンパイルされたので、ダンプのエンクレーブ制御ブロック・セクションで WSA アドレスを探します。この例では、アドレスは X'20914F50' です。図 4 に WSA アドレスを示します。

    図 4. ダンプの C/C++ CAA 情報 (C/C++ ルーチンのゼロ除算エラー)
      Enclave Control Blocks:                                                                                                           
    ⋮                                                                                                                                  
        WSA address.................20914F50                                                                                  
    ⋮                                                                                                                                   
  4. 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                                                                       
    ⋮ 
  5. WSA アドレス X'20914F50'statint のオフセットに加算します。その結果、X'20914F50' になります。これは、書き込み可能静的域にある変数 statint のアドレスです。

    書き込み可能静的域は、ダンプのエンクレーブ・ストレージのセクションに 表示されます。ロード・モジュールの場合、書き込み可能静的域は、C/C++ ランタイム環境により C/C++ ユーザー用に割り振られたストレージなので、ユーザー・ヒープ内に入っています。プログラム・オブジェクトでは、書き込み可能静的域はローダーによって割り振られたストレージで、ダンプのプログラム・オブジェクト用 WSA のセクションに示されています。

    この例では、プログラムはプログラム・オブジェクトとしてビルドされています。 書き込み可能静的域は、ダンプのエンクレーブ・ストレージのセクション (図 6 を参照) に 表示されます。

  6. 書き込み可能静的域内の変数 statint を探すためには、出力されているうちで 最も近いアドレス (statint のアドレスより前) を探してください。この場合、アドレスは X'20914F50' です。そこから X'00' 進むと、X'20914F50' の位置です。その位置の値は X'49' (つまり statint は 73) であり、固定小数点除算例外となります。
図 6. ダンプのエンクレーブ・ストレージ・セクション (C/C++ ルーチンのゼロ除算エラー)
  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............................|
⋮