dbx と互換性のあるシンボリック・デバッガーを使用して XL Fortran プログラムをデバッグすることができます。 dbx に関する背景情報を得るには、「AIX General Concepts and Procedures 」を参照してください。 dbx サブコマンドの情報については、「AIX コマンド・リファレンス 」を参照してください。
以下の例は、dbx で解決できる場合のある一般的な XL Fortran の問題を示しています。これは、dbx 機能の小さなサブセットだけを示したもので、Fortran 90 または Fortran 95 割り振り可能配列では使用されなくなったメモリー割り振り手法を使用していますが、このデバッガーを使用したことがない方には、入門書としての役割を果たします。
以下のプログラムは、AIX システム・サブルーチン malloc を使用して実行時に配列を割り振ろうとします。以下のコマンドを使用してプログラムをコンパイルしてからそのプログラムを実行すると、プログラムはメモリー・ダンプを生成します。
xlf95 -qddim testprog.f -o testprog
この時点で、C の malloc ルーチンが正しく機能しているかどうか、あるいは、実行時まで次元がわからない場合に、この方法がメインプログラム内の配列を割り振る方法として正しいかどうか疑問に思うかもしれません。
program main pointer(p, array(nvar,nrec)) real*8 array nvar = 2 nrec = 3 p = malloc(nvar*nrec*8) call test_sub(array, nvar, nrec) end subroutine test_sub(array, nvar, nrec) dimension array(nvar, nrec) array(1,1) = 1. array(2,1) = 2. array(1,2) = 3. array(2,2) = 4. array(1,3) = 5. array(2,3) = 6. write(*, 100) array(1,1), array(2,1), array(1,2), 1 array(2,2), array(1,3), array(2,3) 100 format(//t2,f4.1/t2,f4.1/t2,f4.1/t2,f4.1/ 1 t2,f4.1/t2,f4.1) return end
デバッグ・プロセスは次のように行います。
-> xlf95 -qddim -g testprog.f -o testprog ** main === End of Compilation 1 === ** test_sub === End of Compilation 2 === 1501-510 Compilation successful for file testprog.f.
-> testprog Segmentation fault(coredump) ->
-> dbx testprog core dbx version 3.1 for AIX. Type 'help' for help. reading symbolic information ... [using memory image in core] segmentation violation in test_sub at line 21 in file "testprog.f" 21 array(1,1) = 1. (dbx)
(dbx) where test_sub(array = (...), nvar = warning: Unable to access address 0x200aee94 from core -1, nrec = warning: Unable to access address 0x200aee98 from core -1), line 21 in "testprog.f" main(), line 12 in "testprog.f" (dbx)
main は 12 行目の test_sub を呼び出します。この警告は、この呼び出しに対して引き数を評価しているときに問題が発生することを示しています。
(dbx) print array(1,1) reference through nil pointer (dbx)
array に値が割り当てられていないことを示唆しています。その可能性を確かめるには、配列内のエレメントのアドレスを見てください。
(dbx) p &array(1,1) (nil) (dbx)
XL Fortran は配列のためのスペースを割り振っていないようです。それを確認するには、その配列を指し示しているポインターの値を印刷します。
(dbx) print p warning: Unable to access address 0x200aee90 from core 0xffffffff
(dbx) stop in main [1] stop in main (dbx) run [1] stopped in main at line 7 in file "testprog.f" 7 nvar = 2 (dbx) trace p [3] trace p (dbx) cont initially (at line 8 in "testprog.f"): p = nil segmentation violation in test_sub at line 21 in file "testprog.f" 21 array(1,1) = 1. (dbx) p p nil (dbx)
p は有効な値に設定されないので、配列にスペースを割り振っている行に何か誤りがあります。
9 p = malloc(nvar*nrec*8)
この項を読むと、C 関数への呼び出しには参照によってではなく値によって引き数を渡す必要があることがわかります。このサンプル・プログラム内の問題を修正するには、
p = malloc(nvar*nrec*8)
行を次の行に置き換えます。
p = malloc(%val(nvar*nrec*8))
-> xlf95 -qddim -g solution.f -o solution ** main === End of Compilation 1 === ** test_sub === End of Compilation 2 === 1501-510 Compilation successful for file solution.f. -> solution 1.0 2.0 3.0 4.0 5.0 6.0
-> dbx solution dbx version 3.1 for AIX. Type 'help' for help. Core file program (testprog) does not match current program (core ignored) reading symbolic information ... (dbx) trace p [1] trace p (dbx) run initially (at line 7 in "solution.f"): p = nil after line 9 in "solution.f": p = 0x200af100 1.0 2.0 3.0 4.0 5.0 6.0 execution completed (dbx)
p と array の値が適切かどうかをチェックするには、トレースをオフにします。
(dbx) status [1] trace p (dbx) delete all (dbx) status (dbx)
次に、新しいブレークポイントを設定して、再びプログラムを最初から終わりまで実行します。予想どおり、array(1,1) のアドレスが p(0x200af100) の内容と同じであることに注目してください。
(dbx) stop at 9 [11] stop at "solution.f":9 (dbx) run [11] stopped in main at line 9 in file "solution.f" 9 p = malloc(%val(nvar*nrec*8)) (dbx) p p nil (dbx) next stopped in main at line 12 in file "solution.f" 12 call test_sub(array, nvar, nrec) (dbx) p p 0x200af100 <------------- (dbx) (dbx) step /* Notice we use step to step into subroutine test_sub. */ stopped in test_sub at line 21 in file "solution.f" 21 array(1,1) = 1. (dbx) p &array(1,1) 0x200af100 <--------------- (dbx) next stopped in test_sub at line 22 in file "solution.f" 22 array(2,1) = 2. (dbx) p array(1,1) 1.0 (dbx)