Compiler errors 检测未初始化的数组

Compiler errors 检测未初始化的数组,compiler-errors,initialization,fortran,runtime-error,Compiler Errors,Initialization,Fortran,Runtime Error,在下面的程序中,两个例程set_int_array和set_real_array为虚拟数组定义了一些值,但假设a(:)和r(:)(第1行和第2行)的初始化无意中丢失(即,在正确的程序中应取消注释这两行)。我的问题是如何使用一些编译器选项自动检测这些错误 为此,我首先为gfortran4.8(在Linux x86_64上)尝试了以下选项: 但这未能检测到缺少的初始化,并给出了不正确的结果 1 2 268435459 32730

在下面的程序中,两个例程
set_int_array
set_real_array
为虚拟数组定义了一些值,但假设
a(:)
r(:)
(第1行和第2行)的初始化无意中丢失(即,在正确的程序中应取消注释这两行)。我的问题是如何使用一些编译器选项自动检测这些错误

为此,我首先为gfortran4.8(在Linux x86_64上)尝试了以下选项:

但这未能检测到缺少的初始化,并给出了不正确的结果

           1           2   268435459       32730         207
   1.0000000       2.0000000       3.0000000       4.0000000       5.0000000
因此,我尝试使用
NaN
初始化
r(:)

gfortran -finit-real=snan -ffpe-trap=invalid test.f90
它成功捕获了
set\u real\u array
的错误,但未捕获
set\u int\u 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 ()
但两者都未能检测到错误。实际上,
check uninit
选项的手册页显示

仅检查内部类型为INTEGER、REAL、COMPLEX和LOGICAL的局部标量变量,而不检查SAVE属性

这样,错误就不会被检测到,这是很自然的。所以我的问题是:是否有任何方法可以自动捕获
a(:)
r(:)
的错误



[编辑]我提出这个问题的动机来自SO,OP很难找到bug。事实证明,问题来自于在
evaluate
模块中的
curve\u derivs\u alg1()
中使用未初始化的数组,但我也很难找到错误的精确位置(尽管一旦发现它可能会显得微不足道!)。
-finit real snan-ffpe trap=invalid
选项在这种情况下起作用,但是如果整数数组是问题所在,那么它应该变得更加困难。。。因此,我想知道是否有一些方便的选项或方法来跟踪未初始化数组的第一个使用位置。

如果您在Linux上,您可以使用
valgrind
完成此任务。如果你发行

valgrind --track-origins=yes ./a.out
您将获得大量输出;-)第一个警告实际上指向未初始化的变量:

==4426== Memcheck, a memory error detector
==4426== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4426== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==4426== Command: ./a.out
==4426== 
==4426== Conditional jump or move depends on uninitialised value(s)
==4426==    at 0x4F29774: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x4F2B2DE: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x4F1F126: _gfortran_transfer_array (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x40098B: MAIN__ (test.F90:34)
==4426==    by 0x400A75: main (test.F90:28)
==4426==  Uninitialised value was created by a stack allocation
==4426==    at 0x4008CD: MAIN__ (test.F90:27)
==4426== Conditional jump or move depends on uninitialised value(s)
==4426==    at 0x4F27BC1: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x4F2A6E4: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x4F2B29E: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x4F1F126: _gfortran_transfer_array (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x400A44: MAIN__ (test.F90:36)
==4426==    by 0x400A75: main (test.F90:28)
==4426==  Uninitialised value was created by a stack allocation
==4426==    at 0x4008CD: MAIN__ (test.F90:27)
为了更好地分析输出,我希望每行有一条语句,因此我将程序的最后几行更改为

    call set_int_array  ( a )
    print *, a(:)
    call set_real_array ( r )
    print *, r(:)
然后,
test.F90:34
指向

    print *, a(:)
稍后,您将发现以下输出指向未初始化变量的第二次使用:

==4426== Memcheck, a memory error detector
==4426== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4426== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==4426== Command: ./a.out
==4426== 
==4426== Conditional jump or move depends on uninitialised value(s)
==4426==    at 0x4F29774: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x4F2B2DE: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x4F1F126: _gfortran_transfer_array (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x40098B: MAIN__ (test.F90:34)
==4426==    by 0x400A75: main (test.F90:28)
==4426==  Uninitialised value was created by a stack allocation
==4426==    at 0x4008CD: MAIN__ (test.F90:27)
==4426== Conditional jump or move depends on uninitialised value(s)
==4426==    at 0x4F27BC1: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x4F2A6E4: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x4F2B29E: ??? (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x4F1F126: _gfortran_transfer_array (in /usr/lib64/libgfortran.so.3.0.0)
==4426==    by 0x400A44: MAIN__ (test.F90:36)
==4426==    by 0x400A75: main (test.F90:28)
==4426==  Uninitialised value was created by a stack allocation
==4426==    at 0x4008CD: MAIN__ (test.F90:27)

请注意,您需要使用调试选项编译代码以获得行号。使用
valgrind
时,从第一个错误开始,一个错误一个错误地纠正也是有益的。这是因为未定义的行为可能会导致后续的错误/警告,这些错误/警告在解决问题的原因后就会消失。

如果检测此类错误对您的工作很重要,您可能需要投资NAG编译器,它可以在运行时报告此类问题。例如,如果我将您的原始代码保存在“test.f90”中并进行编译:

nagfor test.f90 -C=undefined -o test.exe
在运行时,我得到以下结果:

Runtime Error: test.f90, line 11: Reference to undefined variable A(K)
Program terminated by fatal error
Aborted (core dumped)
如果我取消注释并修复了第一个错误,则还会报告第二个错误:

11 12 13 14 15
Runtime Error: test.f90, line 21: Reference to undefined variable R(K)
Program terminated by fatal error
Aborted (core dumped)
编译器通常不执行这种检查,因为它可能很昂贵。也有一些限制。有关更多信息,请访问


请注意,答案来自唠叨的人。上面的链接提供了有关使用'-C=undefined'标志的限制的信息,该标志与此问题没有直接关系,但可能很有用。

我没有足够的资源在这里写答案,但我怀疑
a(:)
不是(在可执行语句中)数组,而是数组节。这是有区别的。这种差异的一个影响是,自动分配可以在赋值的lhs上使用数组执行,但在lhs上使用数组部分无效。@HighPerformanceMark Hi非常感谢您的评论。如果我在问题中的解释有误导性,我很抱歉,但我没有尝试在这两个例程中使用可分配虚拟数组。它们只是从主程序(在主程序中将它们声明为本地数组)传递。在这里,我要寻找的是一种方便的方法,可以找到第一个使用未初始化数组的位置(请参见上面的编辑)。非常感谢您提供的信息。到目前为止,我对valgrind几乎没有经验(只在检查一些有缺陷的C实用程序的内存泄漏时使用过几次),所以我从未使用过它。是的,在Fortran中显示未初始化数组的存在似乎非常有用:)所以我对它进行了实验。我昨天解决了这个问题,并意外地经历了一段很难找到bug的时间。我刚刚尝试了valgrind的这段代码,它给出了大量的错误,但只是在主程序中未初始化值的print语句之后。因此,我能够知道在
\uu evaluate\u MOD\u rat\u curve\u derivs
中存在一个bug,但不能进一步深入到特定的较低子例程中。。。(续)我想追踪这种bug(首先使用未初始化的变量),因此如果存在这种技术,我非常感谢任何提示。(或者,如果有必要,我会把这变成一个问题,尽管我不知道如何提出一个好的问题……)但无论如何,非常感谢你的信息:)@roygvib到目前为止,我还没有找到一种方法来找到它们,将它们全部带到黑暗中绑定它们。它通常是多种工具的组合。。。在我的默认编译选项中有
-finit real=snan-ffpe trap=invalid
(和一些其他选项),如果它们没有指示错误,我会使用valgrind.Hmm之类的工具。。。很高兴知道-finit real的用法。。。这个选择是合理的。我将检查valgrind的更多选项,并尝试适应其用法。谢谢你的建议。编辑了答案。谢谢@macelee,NAG fortran似乎在语法检查方面非常严格。我会试着看看我是否能用上它。谢谢:)
11 12 13 14 15
Runtime Error: test.f90, line 21: Reference to undefined variable R(K)
Program terminated by fatal error
Aborted (core dumped)