在下面的程序中,两个例程set_int_array
and set_real_array
为虚拟数组定义一些值,但假设初始化a(:)
and r(:)
(第 1 行和第 2 行)无意中丢失了(即,这两行在正确的程序中都应该取消注释)。我的问题是如何使用某些编译器选项自动检测这些错误。
module mymod
implicit none
contains
subroutine set_int_array ( a )
integer, intent(out) :: a(:)
integer k
! a(:) = 10 !! (1)
do k = 1, size(a)
a(k) = a(k) + k
enddo
end subroutine
subroutine set_real_array ( r )
real, intent(out) :: r(:)
integer k
! r(:) = 10.0 !! (2)
do k = 1, size(r)
r(k) = r(k) + k
enddo
end subroutine
end module
program main
use mymod
implicit none
integer :: a(5)
real :: r(5)
call set_int_array ( a ) ; print *, a(:)
call set_real_array ( r ) ; print *, r(:)
end program
为此,我首先尝试了 gfortran4.8 的以下选项(在 Linux x86_64 上):
gfortran -Wall -fcheck=all test.f90
但这未能检测到丢失的初始化并给出了错误的结果
1 2 268435459 32730 207
1.0000000 2.0000000 3.0000000 4.0000000 5.0000000
所以我尝试了以下选项来初始化r(:)
with NaN
:
gfortran -finit-real=snan -ffpe-trap=invalid test.f90
成功捕获了错误set_real_array
,但不适合set_int_array
-1098847551 59 -1034862589 32608 7941
Program received signal 8 (SIGFPE): Floating-point exception.
Backtrace for this error:
#0 0x00000039becac5f4 in wait () from /lib64/libc.so.6
#1 0x00000039c501400d in ?? () from /usr/lib64/libgfortran.so.3
#2 0x00000039c501582e in ?? () from /usr/lib64/libgfortran.so.3
#3 0x00000039c50146ca in ?? () from /usr/lib64/libgfortran.so.3
#4 <signal handler called>
#5 0x0000000000400bd3 in __mymod_MOD_set_real_array ()
#6 0x0000000000400e69 in MAIN__ ()
#7 0x0000000000400f52 in main ()
因此,我也尝试了 ifort14.0 的以下选项
ifort -check all test.f90
ifort -check uninit test.f90
但两者都未能检测到错误。事实上,手册页check uninit
选项说
仅限本地scalar检查不带 SAVE 属性的内部类型 INTEGER、REAL、COMPLEX 和 LOGICAL 的变量。
那么错误未被检测到是很自然的。所以我的问题是:有没有什么方法可以捕获这两个错误a(:)
and r(:)
自动地?
[编辑]我提出这个问题的动机来自最近的帖子在 SO 上,OP 很难找到错误。原来问题出在使用了未初始化的数组curve_derivs_alg1()
in the evaluate
模块,但对我来说找到错误的精确位置也非常困难(尽管一旦发现它可能显得微不足道!)。这-finit-real-snan -ffpe-trap=invalid
选项在这种情况下有效,但如果整数数组是问题所在,它应该变得更加困难......所以我想知道是否有一些方便的选项或方法来跟踪使用未初始化数组的第一个位置。