在调试编译的情况下,Fortran 数组似乎可以在 WHERE 条件之外访问

Fortran arrays seems to be accessed outside of WHERE conditions in the case of debug compilation

提问人:acapet 提问时间:10/6/2023 最后编辑:Ian Bushacapet 更新时间:10/7/2023 访问量:111

问:

我正在考虑一个非常复杂的 fortran 代码,其中包含许多相互连接的模块等......因此,我将尽我所能只记录其中非常具体的部分。

在“正常”条件下编译时,代码运行良好(参见下面的详细信息),但是在使用 DEBUG 编译选项时,以下行会导致错误(SIGFPE:浮点异常 - 错误的算术运算)(具有讽刺意味,不是吗?

WHERE (maskatc_int)
   temp_factor = Tfamp*EXP(Tfexp*temp(1:ncloc,1:nrloc,k))
ELSEWHERE
   temp_factor = 0.0
END WHERE

这发生在一个函数中,其中在本地声明temp_factor

REAL, DIMENSION(ncloc,nrloc) :: temp_factor

temp在另一个模块中声明和分配,如

ALLOCATE (temp(1-nhalo:ncloc+nhalo,1-nhalo:nrloc+nhalo,nz),STAT=errstat)

maskatc_int具有良好的尺寸。

ALLOCATE (maskatc_int(ncloc,nrloc),STAT=errstat)

如果有帮助,我可以提供更多细节,但我现在会坚持这些,希望有人已经可以提供解决方案的跟踪(因此,避免在 DEBUG 模式下编译和执行时出现错误)

编译标志 :

'正常' :

# Linux grid0 (GNU Fortran with MPI)
linux-gfortp:
    $(MAKE) $(EXEFILE) "FC=mpif90" "FCOPTS= -O3" "FCDEFS=$(FCDEFS)" \
    "FCDEBUG=" "CPP=" "CPPF=cpp" "CPPOPTS=-traditional-cpp" \
    "CPPDEFS=$(CPPDFLAGS)"

'debug' :

# Linux gfortran debugging (GNU Fortran)
linux-gfort-g:
    $(MAKE) $(EXEFILE) "FC=gfortran" "FCOPTS=" "FCDEFS=$(FCDEFS)" \
    "FCDEBUG=-fbounds-check -Wall -ffpe-trap=invalid,zero,overflow -fimplicit-none - 
fbacktrace" \
        "CPP=" "CPPF=cpp" "CPPOPTS=-traditional-cpp" "CPPDEFS=$(CPPDFLAGS)"
调试 Fortran Gfortran

评论

4赞 Vladimir F Героям слава 10/6/2023
你应该展示一个完整的最小可重现的例子。该链接还包含如何将此类示例与较大代码隔离的建议。
4赞 francescalus 10/6/2023
“数组似乎在 WHERE 条件之外访问”是什么意思,这与引发的浮点异常有什么联系?如果您需要帮助来追踪 FPE,我们需要看到一个最小的可重现示例
5赞 francescalus 10/6/2023
在调试版本中引发浮点异常,要求捕获浮点异常,这似乎远非我想象的“讽刺”。从这一点和标题来看,您似乎很可能误解了您遇到的问题。在最小可重复的例子上工作确实有助于确保每个人都能看到同样的东西。

答:

2赞 hbhbnr 10/6/2023 #1

只有在使用 debug 选项进行编译时才会出现浮点异常的原因是以下参数:

-ffpe-trap=invalid,zero,overflow

当您将其添加到正常编译选项中时,程序也将在正常模式下失败。

您可以在 -ffpe-trap=list 的文档中找到有关这些调试选项的更多详细信息。仅将三个中的一个逐个激活,以查看导致异常的原因。该文档包含示例:

  • invalid:无效的浮点运算,例如SQRT(-1.0)
  • 零:除以
  • 出:浮点运算中的溢出

您的代码使用乘法,因此很可能会造成溢出

当使用以下方法编译时,此最小可重现示例失败并出现相同的 FPE 异常:-ffpe-trap=overflow

program fpe
    real :: a = 1000000000.0
    a = a ** a
end program fpe

结果:

Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation.