ここでは、他のコンパイラで見落とされることが多いプログラム上のエラーをいくつか紹介します。
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
