nAG Fortran コンパイラ(Fortran Builder)では、コンパイラオプション -C=... を付けることによって、実行時のエラーチェックを強化することができます。
具体的には、以下の項目をチェックすることができます。
| : 別名による仮変数の変更 |
| : 配列の範囲 |
| : ビット組込み関数の引数 |
| : 手続の参照 |
| : ダングリングポインタ |
| : 増分値 0 の DO ループ |
| : 整数オーバーフロー |
| : ポインタの参照 |
| : OPTIONAL 引数の参照 |
| : 不正な再帰 |
| : 未定義の変数 |
| : -C=undefined を除くすべてのチェックを行います。 |
| : 時間のかかるチェック -C=alias, -C=dangling, -C=intovf, -C=undefined を除くすべてのチェックを行います。 |
詳細は「nAG Fortran Compiler, Release 7.2 マニュアル - 2.4 コンパイラオプション」をご参照ください。
※ Fortran Builder では、プロジェクトの設定の「Fortran コンパイラ > 実行時診断」から、上記のコンパイラオプションを有効/無効にすることができます。
以下、各チェック項目に対してプログラム例を示します。
別名による仮変数の変更
[ rtc_alias.f90 ]
program main implicit none real x, y call sub(x, y) print *, x call sub(x, x) print *, x contains subroutine sub(a, b) real a, b a = 123 b = 999 end subroutine end program
このプログラムを実行すると、例えば、
1.2300000E+02 9.9900000E+02
コンパイラオプション -C=alias(または -C=all)を付加すれば、
1.2300000E+02 実行時エラー: main.f90, line 11: Aへの代入が、仮引数Bに影響を及ぼします 致命的なエラーでプログラムが終了しました
配列の範囲
[ rtc_array.f90 ]
program main
implicit none
integer i, x(3)
x = 999
do i = 1, 5
print *, x(i) ! 配列の範囲外 x(4), x(5) を参照している。
end do
end program
このプログラムを実行すると、例えば、
999 999 999 1 37879340
コンパイラオプション -C=array(または -C, -C=all)を付加すれば、
実行時エラー: rtc_array.f90, line 6: Xの第1添字(値 4)が範囲外です(1:3) 致命的なエラーでプログラムが終了しました
ビット組込み関数の引数
program main
implicit none
integer i
do i = 1, 32
print *, ibset(0, i) ! ここで i は 0~31 の範囲の値でなければならない!
end do
end program
このプログラムを実行すると、例えば、
2 4 8 16 ... 536870912 1073741824 -2147483648 1
コンパイラオプション -C=bits(または -C, -C=all)を付加すれば、
実行時エラー: rtc_bits.f90, line 5: 組込みIBSETのPOS引数(32)が範囲外です(0:31) 致命的なエラーでプログラムが終了しました
手続の参照
subroutine add_print(a, b) implicit none real, intent(in) :: a, b print *, a + b end subroutine
program main
implicit none
integer :: a = 2, b = 3
call add_print(a, b) ! 実数の仮引数に整数の実引数を渡している。
end program
このプログラムを実行すると、例えば、
7.0064923E-45
コンパイラオプション -C=calls(または -C, -C=all)を付加すれば、
実行時エラー: rtc_calls_sub.f90, line 1: 無効な手続き参照- 仮引数Aの実引数がREAL(real32)ではなくINTEGER(int32)です 致命的なエラーでプログラムが終了しました
ダングリングポインタ
[ rtc_dangling.f90 ]
program main
implicit none
integer, pointer :: p(:)
integer, target, allocatable :: x(:)
allocate (x(3))
x = (/ 1, 2, 3 /)
p => x
deallocate (x)
print *, p ! 解放されたメモリ領域を参照している。
end program
このプログラムを実行すると、例えば、
0 0 3
コンパイラオプション -C=dangling(または -C=all)を付加すれば、
実行時エラー: rtc_dangling.f90, line 9: 遊離した(dangling)ポインタPへの参照が行われました 指示先がrtc_dangling.f90の8行目で解放されています 致命的なエラーでプログラムが終了しました
増分値 0 の DO ループ
[ rtc_do.f90 ]
program main
implicit none
integer i, s
s = 0
do i = 1, 10, s ! ループの増分値が 0 である。
print *, i
end do
end program
このプログラムを実行すると、何も出力されません。
コンパイラオプション -C=do(または -C, -C=all)を付加すれば、
実行時エラー: rtc_do.f90, line 5: DOの増分値がゼロです 致命的なエラーでプログラムが終了しました
整数オーバーフロー
[ rtc_intovf.f90 ]
program main
implicit none
integer n
n = huge(n)
print *, n + 1 ! 整数の最大値に 1 を加算している。
end program
このプログラムを実行すると、例えば、
-2147483648
コンパイラオプション -C=intovf(または -C=all)を付加すれば、
実行時エラー: rtc_intovf.f90, line 5: 2147483647+1でINTEGER(int32)オーバーフローが発生しました 致命的なエラーでプログラムが終了しました
ポインタの参照
program main
implicit none
real, pointer :: x(:)
print *, size(x) ! 未定義のポインタを参照している。
end program
このプログラムを実行すると、例えば、
1254272
コンパイラオプション -C=pointer(または -C, -C=all)を付加すれば、
実行時エラー: rtc_pointer_undef.f90, line 4: 不定ポインタXへの参照が行われました 致命的なエラーでプログラムが終了しました
program main
implicit none
real, pointer :: y(:) => null()
print *, size(y) ! 空状態のポインタを参照している。
end program
このプログラムを実行すると、例えば、
0
コンパイラオプション -C=pointer(または -C, -C=all)を付加すれば、
実行時エラー:rtc_pointer_null.f90, line 4: 空状態のポインタYへの参照が行われました 致命的なエラーでプログラムが終了しました
OPTIONAL 引数の参照
program main
implicit none
integer :: a = 2, b = 3
call add_print(a, b)
contains
subroutine add_print(a, b, c)
integer, intent(in) :: a, b
integer, intent(in), optional :: c
print *, a + b + c ! 省略された引数 c を参照している。
end subroutine
end program
このプログラムを実行すると、プログラムがハングアップします。
コンパイラオプション -C=present(または -C, -C=all)を付加すれば、
実行時エラー: rtc_optional_arg.f90, line 9: 存在しない省略可能引数Cへの参照が行われました 致命的なエラーでプログラムが終了しました
不正な再帰
program main
implicit none
call dispatch(p1, 111)
contains
subroutine dispatch(p, n) ! 再帰的な手続きに RECURSIVE が付いていない。
interface
subroutine p
end subroutine
end interface
integer, intent(in) :: n
integer x(1000, 1000)
x = n
print *, 'Hello', x(1, 1)
call p
print *, 'Goodbye', x(1, 1)
end subroutine
subroutine p1
call dispatch(p2, 999)
end subroutine
subroutine p2
print *, 'Hello World'
end subroutine
end program
このプログラムを実行すると、例えば、
Hello 111 Hello 999 Hello World Goodbye 999 Goodbye 999
コンパイラオプション -C=recursion(または -C, -C=all)を付加すれば、
実行時エラー: rtc_recursion.f90, line 5: 再帰呼出しが非再帰手続きMAIN:DISPATCHに対して行われました 致命的なエラーでプログラムが終了しました
未定義の変数
program main
implicit none
integer i, x(5)
do i = 1, 3
x(i) = i
end do
print *, x ! 未定義の要素 x(4), x(5) を参照している。
end program
このプログラムを実行すると、例えば、
1 2 3 0 1581952
コンパイラオプション -C=undefined を付加すれば、
実行時エラー: rtc_undefined.f90, line 7: 定義されていない変数Xへの参照が行われました 致命的なエラーでプログラムが終了しました