ここでは、他のコンパイラで見落とされることが多いプログラム上のエラーをいくつか紹介します。
nAG Fortran コンパイラ(Fortran Builder)は、これらのエラーをすべて検出することができます。
A. 比較的容易に検出されるべきエラー | |||
プログラム単位内のコンパイルエラー | |||
1. EQUIVALENCE 経由の DO ループ制御変数の変更 | ◯ | ||
配列範囲外参照 | |||
2. 配列の範囲外参照 | ◯ | ||
3. 形状引継ぎ配列の範囲外参照 | ◯ | ||
4. パラメタ化構造型配列の範囲外参照 | ◯ | ||
配列の形状不適合 | |||
5. 配列引数の寸法の不一致 | ◯ | ||
6. 寸法が異なる配列の代入 | ◯ | ||
遊離状態のポインタ、割付けされていない状態の配列への参照 | |||
7. 未定義ポインタの参照 | ◯ | ||
8. 空状態のポインタの参照 | ◯ | ||
省略された引数の参照 | |||
9. 省略された引数の参照 | ◯ | ||
DOループの増分値がゼロ | |||
10. DOループの増分値がゼロ | ◯ | ||
文字引数の長さの不一致 | |||
11. 文字引数の長さの不一致 | ◯ | ||
パラメタ化構造型の長さ型パラメタの不一致 | |||
12. 組込拡張型代入における変数と式の型パラメタの不一致 | ◯ | ||
13. 組込拡張型代入で変数と式の型パラメタが不一致の状態で代入 | ◯ | ||
引数の長さ型パラメタの不一致 | |||
14. 仮引数と実引数で拡張型の型パラメタが異なる | ◯ | ||
スレッドセーフ関連 | |||
15. 誤った純粋手続 | ◯ | ||
16. スレッドセーフではないコードの検出 | ◯ | ||
B. 比較的検出が困難と思われるエラー | |||
大域的チェックを伴うファイル内のコンパイルエラー | |||
17. 実引数と仮引数の型の不一致 | ◯ | ||
18. 名前付き共通ブロックの大きさの不一致 | ◯ | ||
大きさ引継ぎ配列の範囲外参照 | |||
19. 大きさ引き継ぎ配列の範囲外参照 | ◯ | ||
ビット組込関数の不適切な引数 | |||
20. ビット組込み関数への誤った引数 | ◯ | ||
整数オーバーフロー | |||
21. 整数オーバーフロー | ◯ | ||
解放済みポインタの参照 | |||
22. 解放済のポインタの利用 | ◯ | ||
非再帰手続の再帰的な利用 | |||
23. 再帰的に呼び出された手続が非再帰 | ◯ | ||
誤った型の引数 | |||
24. 誤った型の引数 | ◯ | ||
変更してはいけない仮引数の変更 | |||
25. 定数(パラメタ)引数の変更 | ◯ | ||
26. サブルーチン内での DO ループ制御変数の変更 | ◯ | ||
未定義変数の参照 | |||
27. 割付け配列の初期化忘れ | ◯ | ||
28. 配列の部分的な初期化忘れ | ◯ | ||
29. 大きさ引き継ぎ配列の初期化忘れ | ◯ | ||
30. 固定サイズ配列の初期化忘れ | ◯ | ||
31. 共通ブロックの初期化忘れ | ◯ | ||
32. モジュール変数の初期化忘れ | ◯ |
※ 上記のエラー項目の検出を有効にするには、コンパイラオプション -C=... が必要です。
詳細は「nAG Fortran Compiler, Release 7.2 マニュアル - 2.4 コンパイラオプション」をご参照ください。
※ Fortran Builder では、プロジェクトの設定の「Fortran コンパイラ > 実行時診断」から、コンパイラオプション -C=... を有効/無効にすることができます。
1. EQUIVALENCE 経由の DO ループ制御変数の変更
[ ce_dovar.f90 ]
program main implicit none integer i, j equivalence(i, j) j = 0 do i = 1, 10 j = j + 1 ! ここで値を変更してはいけない! print *, i end do end program
このエラーを有効にするためのコンパイラオプション
-C=all
2. 配列の範囲外参照
[ 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
このエラーを有効にするためのコンパイラオプション
-C=all
3. 形状引継ぎ配列の範囲外参照
[ rtc_ashape.f90 ]
Program test_assumed_shape Implicit None Call test([1,2,3]) Contains Subroutine test(x) Integer,Intent(In) :: x(:) Integer i Do i=1,10 Print *,x(i) End Do End Subroutine End Program
このエラーを有効にするためのコンパイラオプション
-C=all
4. パラメタ化構造型配列の範囲外参照
Program rtc_pdtbounds Implicit None Type t(k) Integer,Len :: k Real c(k) End Type Type(t(7)) x x%c = [ 1,2,3,4,5,6,7 ] Call test(x) Contains Subroutine test(y) Type(t(*)),Intent(In) :: y Integer i Do i=1,10 Print *,y%c(i) End Do End Subroutine End Program
このエラーを有効にするためのコンパイラオプション
-C=all
5. 配列引数の寸法の不一致
[ rtc_shape_mismatch_in_sub.f90 ]
program main implicit none integer x(3) x = 99 call sub(x, 4) print *, x end program subroutine sub(a, n) implicit none integer n integer a(n) ! 配列の寸法が一致していない! a(1) = 100 end subroutine
このエラーを有効にするためのコンパイラオプション
-C=all
6. 寸法が異なる配列の代入
[ rtc_shape_mismatch_assignment.f90 ]
program main implicit none integer a(3) call sub(a) print *, a contains subroutine sub(x) integer x(:), y(1) y = 99 x = y ! x と y の寸法が異なる! end subroutine end program
このエラーを有効にするためのコンパイラオプション
-C=all
7. 未定義ポインタの参照
program main implicit none real, pointer :: x(:) print *, size(x) ! 未定義のポインタを参照している。 end program
このエラーを有効にするためのコンパイラオプション
-C=all
8. 空状態のポインタの参照
program main implicit none real, pointer :: y(:) => null() print *, size(y) ! 空状態のポインタを参照している。 end program
このエラーを有効にするためのコンパイラオプション
-C=all
9. 省略された引数の参照
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=all
10. 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=all
11. 文字引数の長さの不一致
[ rtc_charlen.f90 ]
program main implicit none character(3) c c = 'abc' call sub(c, 4) print *, c end program subroutine sub(a, n) implicit none integer n character a(n) ! 文字長が一致していない! a(1:1) = 'X' end subroutine
このエラーを有効にするためのコンパイラオプション
-C=all
12. 組込拡張型代入における変数と式の型パラメタの不一致
Program rtc_pdt_len_params Implicit None Type t(k) Integer,Len :: k Real c(k) End Type Type(t(7)) x x%c = [ 1,2,3,4,5,6,7 ] Call test(x) Contains Subroutine test(y) Type(t(*)),Intent(In) :: y Type(t(10)) :: z Integer i z = y Do i=1,10 Print *,z%c(i) End Do End Subroutine End Program
このエラーを有効にするためのコンパイラオプション
-C=all
13. 組込拡張型代入で変数と式の型パラメタが不一致の状態で代入
Program rtc_pdt_len_params2 Implicit None Type t(k) Integer,Len :: k Real c(k) End Type Type(t(7)) x x%c = [ 1,2,3,4,5,6,7 ] Call test(x,7) ! Okay Call test(x,3) ! Bad Call zap(123) Call test(x,123) ! Also bad Contains Subroutine zap(n) Integer,Intent(In) :: n Real r(n) Real,Allocatable :: a(:) Call Random_Number(r) a = r*100 If (Sum(a)==100*n) Stop 'Unbelievable' End Subroutine Subroutine test(y,n) Type(t(*)),Intent(InOut) :: y Integer,Intent(In) :: n Type(t(n)) :: z Integer i Real s Print *,'Assignment of K',y%k,'expression to K',z%k,'variable' z = y s = 0.0 Do i=1,n s = s + z%c(i) z%c(i) = -z%c(i) End Do Print *,'Sum =',s End Subroutine End Program
このエラーを有効にするためのコンパイラオプション
-C=all
14. 仮引数と実引数で拡張型の型パラメタが異なる
[ rtc_pdt_arg.f90 ]
Program rtc_pdt_arg Implicit None Type t(k) Integer,Len :: k Real c(k) End Type Type(t(7)) :: x x%c = 0 Call sub1(x) Call sub2(x,7) Call sub2(x,999) Contains Subroutine sub1(y) Type(t(*)) y Print *,'Y%K =',y%k If (Any(y%c/=0)) Stop 'FAIL value' End Subroutine Subroutine sub2(z,n) Integer,Intent(In) :: n Type(t(n)) :: z Print *,'Z%K =',z%k If (n/=z%k) Then Print *,'Z declared as TYPE(T(N)), but with N =',n,', Z%K =',z%k Stop 'FAIL z%k/=n' End If If (n/=7) Stop 'FAIL Actual arg has X%K = 7' If (Any(z%c/=0)) Stop 'FAIL value' End Subroutine End Program
このエラーを有効にするためのコンパイラオプション
-C=all
15. 誤った純粋手続
[ purity.f90 ]
! This function is not pure, because it writes to global variables. Pure Real Function f(x,y) Real,Intent(In) :: x,y Real :: z Common/c/z(2) Real,External :: sum_of_z z(1) = x z(2) = y f = sum_of_z() End Function ! This function is pure, as although it reads from global variables, ! it does not change any. Pure Real Function sum_of_z() Real z Common/c/z(2) sum_of_z = Sum(z) End Function ! This function is thread-safe, but not pure: although it has no side-effects, ! the dummy arguments have not had their INTENT declared. Real Function g(x,y) Real x,y g = x + y**2 End Function
このエラーを有効にするためのコンパイラオプション
オプションは必要ありません。
16. スレッドセーフではないコードの検出
[ threadsafety.f90 ]
! This function is not thread-safe, because it writes to global variables. Real Function f(x,y) Real,Intent(In) :: x,y Real :: z Common/c/z(2) Real,External :: sum_of_z z(1) = x z(2) = y f = sum_of_z() End Function ! This function is thread-safe, as although it reads from global variables, ! it does not change any. Real Function sum_of_z() Real z Common/c/z(2) sum_of_z = Sum(z) End Function ! This function is thread-safe, as it has no side-effects. Real Function g(x,y) Real x,y g = x + y**2 End Function
このエラーを有効にするためのコンパイラオプション
-thread_safe
17. 実引数と仮引数の型の不一致
[ gcheck.f90 ]
Program gcheck Real x(10) External sub Call sub(x,10) Print *,'FAIL',x End Program Subroutine sub(y,n) ! Different data type. Integer n,y(n) y = 42 End Subroutine
このエラーを有効にするためのコンパイラオプション
-C=all
18. 名前付き共通ブロックの大きさの不一致
[ gcommon.f90 ]
Program gcommon Common/c/w,x,y,z w = 2.5 Call sub Print *,w,x,y,z End Program Subroutine sub Common/c/w,xy,z ! Note the missing comma. x = w ** 2 y = x * w z = y * x End Subroutine
このエラーを有効にするためのコンパイラオプション
-C=all
19. 大きさ引き継ぎ配列の範囲外参照
program main implicit none integer x(3) x = 99 call sub(x) end program subroutine sub(i) implicit none integer i(*) i(4) = 100 ! 配列の範囲外を参照している! end subroutine
このエラーを有効にするためのコンパイラオプション
-C=all
20. ビット組込み関数への誤った引数
program main implicit none integer i do i = 1, 100 print 10, ibset(0, i) ! ここで i は 0~31 の範囲の値でなければならない! 10 format (1x, z0) end do end program
このエラーを有効にするためのコンパイラオプション
-C=all
21. 整数オーバーフロー
[ rtc_intovf.f90 ]
program main implicit none integer n n = huge(n) print *, n + 1 ! 整数の最大値に 1 を加算している! end program
このエラーを有効にするためのコンパイラオプション
-C=all
22. 解放済のポインタの利用
[ rtc_dangling.f90 ]
program main implicit none integer, pointer :: p(:) => null() integer, target, allocatable :: a(:) allocate (a(4)) a = (/ 1, 2, 3, 4 /) p => a deallocate (a) print *, p ! 解放されたメモリ領域を参照している! end program
このエラーを有効にするためのコンパイラオプション
-C=all
23. 再帰的に呼び出された手続が非再帰
integer function func_recursively_called(func_to_call, n) implicit none external func_to_call integer n, m(1000, 1000), func_to_call m = n if (n < 2) then func_recursively_called = func_to_call(func_to_call, n + 1) end if if (any(m /= n)) then func_recursively_called = -999 ! おかしい! else func_recursively_called = 0 ! OK endif end function program main implicit none external func_recursively_called integer func_recursively_called if (func_recursively_called(func_recursively_called, 1) == 0) then print *, 'OK. No error.' else print *, 'NG. BAD' endif end program
このエラーを有効にするためのコンパイラオプション
-C=all
24. 誤った型の引数
program main implicit none integer :: a = 2, b = 3 call add_print(a, b) ! 実数の仮引数に整数の実引数を渡している。 end program
subroutine add_print(a, b) implicit none real, intent(in) :: a, b print *, a + b end subroutine
このエラーを有効にするためのコンパイラオプション
-C=all
25. 定数(パラメタ)引数の変更
program main implicit none integer, parameter :: x = 99 call sub(x) print *, x end program subroutine sub(i) implicit none integer i i = 10 ! i は定数なので変更してはいけない! end subroutine
このエラーを有効にするためのコンパイラオプション
-C=all
26. サブルーチン内での DO ループ制御変数の変更
program main implicit none integer i do i = 1, 10 call sub(i) print *, i end do end program subroutine sub(i) implicit none integer i i = i + 1 ! ここで値を変更してはいけない! end subroutine
このエラーを有効にするためのコンパイラオプション
-C=all
27. 割付け配列の初期化忘れ
program main implicit none integer, allocatable :: a(:) allocate (a(3)) call sub(a) end program subroutine sub(x) implicit none integer x(3) print *, x ! 初期化されていない x を参照している! end subroutine
このエラーを有効にするためのコンパイラオプション
-C=undefined
28. 配列の部分的な初期化忘れ
[ rtc_undef_partial_undef.f90 ]
program main implicit none integer i, x(4) do i = 1, 3 x(i) = i end do print *, x ! 部分的に初期化されていない x を参照している! end program
このエラーを有効にするためのコンパイラオプション
-C=undefined
29. 大きさ引き継ぎ配列の初期化忘れ
[ rtc_undef_assumed_size.f90 ]
program main implicit none integer i(4) call sub(i) end program subroutine sub(i) implicit none integer i(*) print *, i(1) ! 初期化されていない i(1) を参照している! end subroutine
このエラーを有効にするためのコンパイラオプション
-C=undefined
30. 固定サイズ配列の初期化忘れ
program main implicit none integer i(4) call sub(i) end program subroutine sub(i) implicit none integer i(4) print *, i(1) ! 初期化されていない i(1) を参照している! end subroutine
このエラーを有効にするためのコンパイラオプション
-C=undefined
31. 共通ブロックの初期化忘れ
program main implicit none integer x common /nAG/ x print *, x ! 初期化されていない x を参照している! end program
このエラーを有効にするためのコンパイラオプション
-C=undefined
32. モジュール変数の初期化忘れ
module mymod integer x end module program main use mymod print *, x ! 初期化されていない x を参照している! end program
このエラーを有効にするためのコンパイラオプション
-C=undefined