Gfortran -Wuninitialized标志在do循环中错过变量

时间:2016-09-20 10:07:44

标签: loops fortran gfortran gcc-warning compiler-flags

请考虑以下代码:

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标志来创建一个容易跟踪的垃圾踪迹,如果变量未初始化的话。有更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

假定错误的特征

对于初学者来说,准确地缩小这个(假定的)错误发生的时间是有帮助的,在我看来,如果这两个条件都成立,就会发生这种情况:

  1. 在 do 循环内
  2. 变量出现在左右两侧(例如 x=x+1

无论变量是隐式还是显式声明,它们是整数还是实数似乎都无关紧要。

因此,虽然这看起来确实是一个编译器错误,但情况非常有限,-Wuninitialized 将捕获绝大多数带有未初始化变量的错误,即使在 do 循环内部也是如此。

此外,虽然 -Wuninitialized 在上述情况下会失败,但还有一些其他 gfortran 编译器标志在这里非常有用,至少在实数方面 - 我不知道有什么方法可以捕获整数。请参阅下面的几个选项。

gfortran version = 5.5.0(在 linux 系统上测试)

用于捕获未声明实数的选项 1

shell 命令:

> gfortran -finit-real=snan main.f90
> ./a.out

输出:

noninit =               NaN

注意事项:

  1. 这不会给出编译器警告,也不会导致运行时错误,但它将 NONINIT 初始化为 NaN 而不是零,这更有可能让您发现这里的问题,但显然这取决于了解您的程序稍后使用 NONINIT 究竟做了什么。
  2. 因为这个选项显式地将实数初始化为 NaN,它否定了您从 -Wuninitialized 得到的任何实数警告,因为现在没有实数会被未初始化!但是对于大多数未初始化的整数,您仍然应该收到警告。

用于捕获未声明实数的选项 2

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

注意事项:

  1. -ffpe-trap 的重要选项是“无效”,但我包含了“零”和“溢出”,只是因为使用此标志的大多数人似乎都使用这三个选项。
  2. 需要 -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 拥有丰富的调试工具,也能抓住它。