第 5 章 デバッグのチュートリアル

この章では、Animator の使用方法を具体例を通じて説明します。文中で使用しているサンプルプログラムは、demo ディレクトリに格納されています。これらのサンプルプログラムの検索には、Infomgr を利用できます。詳細については、『Utilities Handbook』『Infomgr』 の章を参照してください。

5.1 標準的なデバッグ

Animator では、コンパイラが生成するあらゆるレベルのコードをデバッグできます。.int ファイルや .gnt ファイル、または .so ファイルをデバッグするには、特定のオプションをコンパイラに渡す必要があります。次に示す例では、サンプルプログラムとして pi.cbl を使用します。

『Server Express ユーザガイド』 の次の各章も参照してください。

次の表は、各種の実行可能ファイルの生成方法と、Animator での使用方法をまとめています。

実行可能ファイルの種類
コンパイル方法
Animator の起動方法
.int ファイル
cob -ia pi.cbl 
anim pi.int
.gnt ファイル
cob -ug -C anim pi.cbl 
anim pi.gnt 
.so ファイル
cob -zg -C anim pi.cbl 
anim pi.so
システム実行可能ファイル
cob -xg -C anim pi.cbl 
anim pi

5.2 JIT デバッグ

JIT (Just-In-Time) デバッグとは、プログラムが実行時エラーで終了したときに Animator を起動し、プログラムのデバッグを開始する方法です。この方法を使えば、プログラムの異常発生時の状態を知ることができます。次に紹介する例では、サンプルプログラムとして ticerr.cbl を使用します。

JIT デバッグを実行するには、実行時構成ファイルに debug_on_error 実行時調整変数を追加する必要があります。次のような行を追加します。

set debug_on_error=1 

実行時構成ファイルでは、起動するデバッガの種類も指定できます。デフォルトでは cobanim が指定されており、Animator は X ウィンドウ上の独立したウィンドウで起動します。したがって、別のデバッガを指定する必要は特にありませんが、たとえば次の行を追加すれば anim を指定できます。

set debugger_command="anim"

さらに、デバッガのコマンドに追加する指令も指定できます。たとえば、cobanim コマンドに mixedlangdebug 指令を追加するには、次のように記述します。

set debugger_command="cobanim mixedlangdebug"

構成ファイルがランタイムシステムに読み取られるように、次のコマンドで構成ファイルをエクスポートします。

export COBCONFIG=$HOME/cobopt.cfg

実行時構成ファイルと実行時調整変数の詳細については、『Server Express ユーザガイド』『実行時の構成』 の章を参照してください。

サンプルプログラム (ticerr.cbl) には、デバッグ用のエラーが含まれています。このファイルを使用して JIT デバッグを実行する手順を次に示します。

  1. 実行時構成ファイルに実行時調整変数を設定します。
    debug_on_error=1
  2. 構成ファイルをエクスポートします。

  3. プログラムをコンパイルします。
    cob -aiv ticerr.cbl 
  4. プログラムを実行します。
    cobrun ticerr.int

Animator が起動し、call dodgy-pointer の行が強調表示されます。

5.3 コアファイルデバッグ

コアファイルデバッグでは、プログラムでエラーが発生した場合に、オペレーティングシステムが生成したコアファイルを使用して、問題の発生原因を詳しく調べることができます。コアファイルは、プログラムが異常終了した時点で当該プロセスに割り当てられていたメモリ領域のスナップショットです。

オペレーティングシステムにコアファイルを生成させるには、実行時構成ファイルに core_on_error 実行時調整変数を追加する必要があります。実行時構成ファイルに次の行を追加します。

set core_on_error=1

実行時構成ファイルと実行時調整変数の詳細については、『Server Express ユーザガイド』『実行時の構成』 を参照してください。


: debug_on_error 実行時調整変数が設定されていると、core_on_error は追加しても無視されます。したがって、core_on_error を追加するときには、debug_on_error への参照をすべて削除する必要があります。


コアファイルデバッグの実行例を次に示します。この例では、サンプルプログラムとして ticerr.cbl を使用します。

  1. 実行時構成ファイルに実行時調整変数の設定を追加します。
    set core_on_error=1
  2. 構成ファイルをエクスポートします。

  3. プログラムをコンパイルします。
    cob -aiv ticerr.cbl
  4. プログラムを実行します。
    cobrun ticerr.int 

    サンプルプログラムにはエラーが含まれているため、オペレーティングシステムによってコアファイルが生成されたことを示すメッセージが表示されます。

  5. 次のコマンドで Animatorを起動し、生成されたコアファイルを表示します。
    anim core

Animator が起動し、call dodgy-pointer の行が強調表示されます。

5.4 動的アタッチによるオンデマンドデバッグ

開発サイクルの中では、プログラムがハングアップしたり、予期しない形で異常終了したり、あるいは異常な動作に陥る可能性があります。プログラムに問題が発生した時点で Animator を起動できれば、そのような状況に効果的に対処できます。それを可能にするのが、動的アタッチメントデバッグです。動的アタッチメントデバッグを実行するには、Animator のアタッチ先プロセスを指定します。

動的アタッチメントデバッグの実行例を次に示します。この例では、サンプルプログラムとして tictac.cbl を使用します。

  1. プログラムをコンパイルします。
    cob -iav csi tictac.cbl
  2. プログラムを実行します。
    cobrun tictac.int

    プログラムが起動してプロンプトが表示されます。この時点では、プロンプトには何も入力しません。

  3. 別のコンソールまたは新しい X ウィンドウに移ります。

  4. 次のコマンドを入力します。myid には自分のユーザ ID を指定してください。
    ps -fumyid | grep tictac.int

    このコマンドは、Tictac を実行しているプロセスを表示します。ここでは、tictac.int への記述項を含むプロセスと、grep コマンドのプロセスの ID を表示します。必要なプロセスは通常、最初に表示され、rts32 が含まれています。たとえば、次のように出力されます。

    myid 36712 83665 0 10:47:53 pts/34 0:00 /home/myid/..../rts32 tictac.int 
    myid 67264 40892 3 10:54:43 pts/20 0:00 grep tictac.int

    各行の最初の数字がプロセス ID です。rts32 tictac.int を含む行が tictac.int を実行しているプロセスです。上の出力例では、このプロセスの ID は 36712 です。

  5. 取得したプロセス ID を指定して Animator を起動します。
    anim 36712

    Animator が起動し、実行中の tictac.int にアタッチされます。この時点では、Animator のメニューは表示されますが、COBOL のソースコードは表示されません。その後、以下のようなプログラムと節のリストが表示されます。:

    +Perform/Call Stack - view---------------------------------------------------+ 
    |Program Name Section Name                                                   | 
    +----------------------------------------------------------------------------+ 
    |ADISKEY2 Program is not animatable                                          | 
    |ADISKEY Program is not animatable                                           | 
    |ADIS Program is not animatable                                              | 
    |...1/kf/gen/src/tmp/tictac.int GET-REPLY                                    | 
    |...1/kf/gen/src/tmp/tictac.int PLAY-1                                       | 
    |                                                                            |
    +----------------------------------------------------------------------------+
    | ^ v =scroll <-+=View Escape                                                |
    +----------------------------------------------------------------------------+

    下矢印キーを押して、GET-REPLY を強調表示させ、Enter キーを押します。実際に、実行処理中である COBOL 文が表示されます。

  6. s キーを押して現在の文にステップインします。

  7. tictac.int を実行している元の端末または X ウィンドウに戻ります。表示されているプロンプトに応答します。

  8. n キーを押します。

  9. Animator を実行している端末または X ウィンドウに戻ります。ACCEPT 文の次の行が強調表示されており、Animator が通常どおりに動作しています。

5.5 混合言語デバッグ

混合言語のプログラミングを行うには Animator のほか、使用している非 COBOL 言語用のシステムデバッガが必要です。COBOL プログラムは Animator でデバッグし、別プロセスで動作している非 COBOL プログラムにはシステムデバッガを使用します。

次に示す実行例では、サンプルプログラムとして cobmain.cblcsub.c を使用します。システムデバッガとしては、AIX システムのデバッガである dbx を使用しています。


: システムデバッガの使用方法については、使用しているシステムのマニュアルを参照してください。本書では、システムデバッガの使用方法には触れません。


  1. COBOL プログラムをアニメート処理用にコンパイルします。
    cob -iav cobmain.cbl
  2. C のプログラムをコンパイルし、共有オブジェクトを作成します。
    cob -zg -e "" csub.c
  3. 次のコマンドで Animator を起動します。
    anim cobmain.int mixedlangdebug

    MIXEDLANGDEBUG 指令によって、Animator はデバッグ対象のプロセス間でパイプインターフェイスを使用できるようになります。

  4. cobmain.int プログラムを通常どおりステップ実行し、次の行に到達した時点で停止します。
    call "csub1" using a b
  5. 別の端末または X ウィンドウに移ります。

  6. 次のコマンドを入力します。
    ps -fu myid | grep cobmain.int

    これにより、dbx にアタッチするプロセスがわかります。実行されている各プロセスの ID が次のように表示されます。

    myid 36712 83665 0 10:47:53 pts/34 0:00 /home/myid/..../rts32 cobmain.int mixedlangdebug
    myid 67264 40892 3 10:54:43 pts/20 0:00 grep cobmain.int

    アタッチするプロセスには、行に rts32 cobmain.int が含まれています。上の例では、該当するプロセスの ID は 36712 です。

  7. 取得したプロセス ID を指定して dbx デバッガを起動し、そのプロセスにアタッチします。
    dbx -a 36712 
  8. 次のコマンドを入力します。
    stop in csub1

    このコマンドによって、dbx は csub1 に制御が入った時点でストップします。

  9. c キーを押します。

    この操作によって、プロセスが実行されます。

  10. Animator が動作している端末または X ウィンドウに戻ります。

  11. s キーを押します。

    この操作によって、csub1 の呼び出しにステップインします。

  12. dbx が動作している端末または X ウィンドウに戻ります。

    dbx は csub1 内で停止しており、区切り点の設定やデータ項目の値の参照などのデバッグ操作を必要に応じて実行できます。

  13. デバッグ操作が完了したら、アタッチを解除します。

    アタッチの解除とは、ptrace のアタッチを解除することです。アタッチを解除しても、Animator とデバッグ対象プログラムの実行は継続されます。ここでアタッチを解除せずにデバッグを継続することもできます。その場合は、dbx がバックグラウンドでそのまま動作し、デバッグ対象プログラムで区切り点が検出されるのを待ちます。

5.6 マルチスレッドプログラムのデバッグ

ここで説明する内容は、読者がマルチスレッドプログラムの開発に精通していることを前提としています。マルチスレッドプログラム開発に関する知識を得るには、『Multi-threaded Programming』 を参照してください。これまでの項で説明した各種のデバッグ手法は、原則的にマルチスレッド版のランタイムシステムを使用したデバッグにも使用できます。

次に、マルチスレッドプログラムのデバッグ例を示します。この例ではサンプルとして、mthread.cblmthreadcore.cblservice.cblservui.cblservwrk.cpyservlnk.cpy、および servdisp.cpy を使用します。

  1. サンプルプログラムをコンパイルします。
    cob -iavt mthread.cbl mthreadcore.cbl service.cbl servui.cbl

    -t は、再エントリによるマルチスレッド化を有効化するオプションです。

  2. サンプルプログラムを実行します。次のようにマルチスレッド版ランタイムシステムのトリガ (cobrun_t) にプログラム名を指定し、Animator 起動用の実行時スイッチ (+A) 付きで実行します。
    cobrun_t +A mthread.int

    : トリガ名の末尾の _t は、マルチスレッド版ランタイムシステム用のトリガであることを示しています。cobrunanim、および cobanim の各トリガには、それぞれ対応するマルチスレッド版のトリガが存在します。すなわち、cobrun_tanim_t、および cobanim_t です。
  3. v キーを押してスレッドを表示します。

    2 つのスレッドが表示されます。1 つは不明スレッド、もう 1 つは mthread.int を実行しているスレッドです。不明スレッドはランタイムシステム自体のスレッドです。このスレッドは COBOL プログラムではなく、アニメート処理の対象外であるため、無視してください。

  4. Esc キーを押し、〔View-thread〕ボックスを閉じます。

  5. 下矢印キーを押して、mthread.int のソースコード内の次の部分まで移動します。
           
            *> Create service thread 
            *> 
             move thread-count-id to service-id 
             start 'service' using by content service-linkage 
             identified by current-req-thread 
             if return-code not = 0 
                 move service-id to service-done-id 
                 move 78-DONE-ABORT to service-done-type 
             perform send-message  
             else 
     ------>     add 1 to thread-count-id  
                 thread-count 
             end-if

    矢印で示されている行にカーソルを置きます。

  6. bs の順でキーを押し、カーソル位置の行に区切り点を設定します。

  7. z キーを押し、mthread.int プログラムを Zoom モードで実行します。

  8. mthread.int を実行しているウィンドウに切り替えます。

  9. 1 キーを押してスレッドを開始します。設定した区切り点で Animator が停止します。

  10. Animator ウィンドウに切り替えます。

  11. z キーを押し、mthread.int プログラムをもう一度 Zoom モードで実行します。

  12. mthread.int を実行しているウィンドウに切り替えます。

  13. 2 キーを押して別のスレッドを開始します。設定した区切り点で Animator が停止します。

  14. Animator ウィンドウに切り替えます。

  15. v キーを押してスレッドを表示します。

    スレッドを表示すると、実行中のスレッドがまだあることに気付くはずです。現在のスレッドとは別のスレッドを強調表示して Enter キーを押すと、そのスレッドで実行されているコードが表示されます。

この例からもわかるとおり、マルチスレッドプログラムのデバッグ方法は、管理すべきプログラムが複数に及ぶという点を除けば、シングルスレッドプログラムの場合に似ています。ただし、マルチスレッドプログラムのデバッグでは、Animator で利用できる機能がいくつか追加されます。その 1 つが、上記の例でも紹介したスレッド表示 (View-threads) です。そのほかにも、いずれか 1 つのスレッドのプログラム実行のみを停止する特定スレッド用の区切り点 (Thread-local Breakpoint) などを使用できます。詳細については、『Animator の操作』 の章を参照してください。

コアファイルデバッグ、JIT デバッグ、および動的アタッチによるオンデマンドデバッグは、これまでの該当する項で紹介した具体例とほぼ同じ手順でマルチスレッドプログラムのデバッグに利用できます。ただし、ランタイムシステムのトリガとして、末尾に _t が付いたコマンドを使用する点に注意してください。

一例として、コアファイルを生成する手順を次に示します。

  1. 実行時構成ファイルに次の行を追加し、core_on_error 実行時調整変数を設定します。
    set core_on_error=1
  2. 次のコマンドでプログラムを実行します (mthreadcore.cbl の中間コードへのコンパイルは終了しているものとします。)
    cobrun_t mthreadcore.int 
  3. 1 キーを押します。

  4. 2 キーを押します。

    オペレーティングシステムによってコアファイルが生成されたことを示すメッセージが表示されます。コアファイルは、サービスプログラムを実行するスレッドが 2 つ以上開始された場合に生成されます。なお、高性能なシステムでは、2 つ目のスレッドを開始する前に、最初のスレッドが終了してしまう可能性もあります。そのような場合には、プログラムをもう一度実行してください。

  5. コアファイルを入力に指定して Animator を起動します。
    anim_t core

    Animator が起動し、call dodgy-pointer の行が強調表示されます。スレッドを表示し、必要に応じてスレッド表示を切り替えれば、問題が発生した場合の各スレッドの処理内容を確認できます。

この手順とシングルスレッドプログラムのデバッグの手順の違いは、前者では末尾に _t が付いたトリガを使用するという点です。

5.7 CBL_DEBUGBREAK ルーチン

CBL_DEBUGBREAK は実行時ライブラリルーチンの 1 つです。このルーチンを COBOL プログラム内で使用すると、同ルーチンが呼び出された時点で、呼び出した行から Animator によるデバッグが開始されます。ここでは、サンプルプログラムとして ticbreak.cbl を使用し、そのコンパイルと実行を通じて CBL_DEBUGBREAK の機能を示します。

  1. サンプルプログラムをデバッグ用にコンパイルします。
    cob -iav ticbreak.cbl
  2. プログラムを実行します。

    cobrun ticbreak.int

CBL_DEBUGBREAK ルーチンが呼び出されると、ただちに Animator が起動し、ticbreak.cbl プログラムのデバッグを開始できます。

CBL_DEBUGBREAK ルーチンは、COBOL コードの実行中に任意のポイントに Animator をアタッチする手段として効果的です。たとえば、プログラムに次のようなエラーチェックコードが含まれているとします。

if error equals 2 
    display "Should never reach here. It's impossible" 
end-if

このプログラムを実行した結果、メッセージが表示される場合には、次の行を追加します。

call "CBL_DEBUGBREAK"

この行が実行されると Animator が起動し、メッセージが表示される原因になったプログラムのロジックをチェックできます。

CBL_DEBUGBREAK は、複数の言語で開発した複雑な大型アプリケーションをデバッグするときにも役立ちます。COBOL、C などさまざまな言語で書かれたプログラム群を Animator でステップ実行すると、デバッグすべき箇所に到達するまでに、かなりの時間が費やされてしまう場合があります。一方、デバッグすべき関数内に CBL_DEBUGBREAK を追加すれば、アプリケーションをコンパイルして実行するだけで、CBL_DEBUGBREAK を追加した箇所に到達したときに Animator が自動的に起動します。


Copyright © 2006 Micro Focus International Limited. All rights reserved.