0

我正在处理大型 fortran 代码,并且在使用快速选项进行编译之前(为了在大型数据库上执行测试),我通常使用“警告”选项进行编译,以检测和回溯所有问题。

因此,通过gfortran -fbacktrace -ffpe-trap=invalid,zero,overflow,underflow -Wall -fcheck=all -ftrapv -g2编译,我收到以下错误:

Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation.
Backtrace for this error:
 #0  0x7fec64cdfef7 in ???
 #1  0x7fec64cdf12d in ???
 #2  0x7fec6440e4af in ???
 #3  0x7fec64a200b4 in ???
 #4  0x7fec649dc5ce in ???
 #5  0x4cf93a in __f_mod_MOD
    at /f_mod.f90:132
 #6  0x407d55 in main_loop_
    at main.f90:419
 #7  0x40cf5c in main_prog
    at main.f90:180
 #8  0x40d5d3 in main
    at main.f90:68

并且代码 f_mod.f90:132 的部分包含一个 where 循环:

! Compute s parameter
do i = 1, Imax
   where (dprim .ne. 1.0)
      s(:,:,:, :) = s(:,:,:, :) +vprim(:,:,:, i,:)*dprim(:,:,:, :)*dprim(:,:,:, :)/(1.0 -dprim(:,:,:, :))
   endwhere
enddo

但我在这里没有看到任何错误。所有其他位置都是通往这部分的子程序的调用。当然,由于这是一个 SIGFPE 错误,所以我在编译时必须在执行时遇到问题gfortran -g1。(我在 linux 上使用 gfortran 6.4.0)

此外,此错误会随着代码完全不同部分的修改而出现和消失。因此,问题来自这个 where 循环?或者来自其他地方并且回溯是错误的?如果是这种情况,我怎么能找到这个错误?

编辑:

因为,我无法在一个最小的例子中重现这个错误(他们正在工作),我认为问题出在其他地方。但是如何在大代码中找到问题呢?

4

1 回答 1

5

由于代码因 SIGFPE 而死,请使用每个单独的可能陷阱来了解它是 FE_DIVBYZERO、FE_INVALID、FE_OVERFLOW 还是 FE_UNDERFLOW。如果是下溢,请将掩码更改为 '1 - dprim .ne。0'。

PS:当可以使用整个数组引用时,不要使用数组节表示法。

PPS:您可能希望在 do 循环之外计算 dprim*drpim / (1 - dprim),因为它是循环不变的。

于 2018-05-23T18:15:50.723 回答