请考虑以下代码:
PROGRAM TEST
IMPLICIT NONE
REAL:: noninit
noninit = noninit + 1
END PROGRAM TEST
如果使用gfortran -Wall TEST.f90
进行编译,则会‘noninit’ is used uninitialized in this function [-Wuninitialized]
正确生成警告。现在考虑do循环中的相同代码:
PROGRAM TEST
IMPLICIT NONE
REAL:: noninit
INTEGER:: ii
DO ii=1,10
noninit = noninit + 1
END DO
END PROGRAM TEST
当遵循相同的命令时,不会产生未初始化变量的警告。你能解释一下为什么会出现这种情况以及我可以采取哪些措施来解决这个问题?我目前的解决方案是使用-finit-real=snan
标志来创建一个容易跟踪的垃圾踪迹,如果变量未初始化的话。有更好的解决方案吗?
答案 0 :(得分:2)
对于初学者来说,准确地缩小这个(假定的)错误发生的时间是有帮助的,在我看来,如果这两个条件都成立,就会发生这种情况:
x=x+1
)无论变量是隐式还是显式声明,它们是整数还是实数似乎都无关紧要。
因此,虽然这看起来确实是一个编译器错误,但情况非常有限,-Wuninitialized
将捕获绝大多数带有未初始化变量的错误,即使在 do 循环内部也是如此。
此外,虽然 -Wuninitialized
在上述情况下会失败,但还有一些其他 gfortran 编译器标志在这里非常有用,至少在实数方面 - 我不知道有什么方法可以捕获整数。请参阅下面的几个选项。
gfortran version = 5.5.0
(在 linux 系统上测试)
shell 命令:
> gfortran -finit-real=snan main.f90
> ./a.out
输出:
noninit = NaN
注意事项:
-Wuninitialized
得到的任何实数警告,因为现在没有实数会被未初始化!但是对于大多数未初始化的整数,您仍然应该收到警告。shell 命令:
> gfortran -finit-real=snan -ffpe-trap=invalid,zero,overflow -g main.f90
> ./a.out
输出:
Program received signal SIGFPE: Floating-point exception - erroneous
arithmetic operation.
Backtrace for this error:
#0 0x7FCE45AFC697
#1 0x7FCE45AFCCDE
#2 0x7FCE44FF73EF
#3 0x400818 in MAIN__ at main.f90:8
Floating point exception
注意事项:
-ffpe-trap
的重要选项是“无效”,但我包含了“零”和“溢出”,只是因为使用此标志的大多数人似乎都使用这三个选项。-g
标志来查看导致崩溃的行号(如果没有 -g
,它仍然会崩溃,但您不知道它是哪一行)。答案 1 :(得分:1)
这是特定编译器中的特定缺陷。我不确定它是否如我们在评论中所建议的那样报告给 GCC bugzilla。
其他编译器可以捕获它:
> ifort -g -warn -check noninit.f90
> ./a.out
forrtl: severe (194): Run-Time Check Failure. The variable 'test_$NONINIT' is being used in 'noninit.f90(7,5)' without being defined
Image PC Routine Line Source
a.out 0000000000402A2F Unknown Unknown Unknown
a.out 0000000000402992 Unknown Unknown Unknown
libc-2.26.so 00007F009F1A934A __libc_start_main Unknown Unknown
a.out 00000000004028AA Unknown Unknown Unknown
我敢打赌 NAG 拥有丰富的调试工具,也能抓住它。