我有一个相当大的代码(> 6000行),我尝试通过以下非常简化的摘录来说明这个问题:
program TestFortran
implicit none
real, parameter :: eps = 1d-30
real :: res
real :: tmp
call TestInitialisation(res,tmp)
if (res>0 .and. res <eps) then
write(*,*) "res is small but not zero and tmp = ", tmp
res = 0d0
else
write(*,*) "res is zero and tmp = ", tmp
end if
contains
subroutine TestInitialization(output,out2)
real,intent(out) :: output
real,intent(out) :: out2
real :: origa(10,10)
real :: copya(10,10)
origa = 0d0
copya = origa
call TIS1(copya,output,out2)
end subroutine TestInitialization
subroutine TIS1(arr2d,ret,out2)
real,intent(in) :: arr2d(:,:)
real,intent(out) :: ret
real,intent(out) :: out2
integer :: ii
do ii = 1,size(arr2d,2)
call TIS2(arr2d(:,ii),ii,ret,out2)
if (ret > 0) then
exit
end if
end do
end subroutine TIS1
subroutine TIS2(arr1d,jj,ret,out2)
real,intent(in) :: arr1d(:)
real,intent(out) :: ret
real,intent(out) :: out2
integer :: ii
integer,intent(in):: jj
do ii = 1,size(arr1d)
ret = arr1d(ii)
out2 = real(jj)
if (ret > 0) then
out2 = -1d0
exit
end if
end do
end subroutine TIS2
end program TestFortran
实际程序在调试模式下确实可以正常工作。但是,在发布模式(带有intel编译器2017的Visual Studio 2017)中,切换/ O3,res
值只是垃圾(如1.0831d-273,但是我不确定天气如何在调试优化后信任变量资源管理器码)。我无法用上面的示例来重现这种情况,它只是作为说明(tmp
变量是因为它不仅可以优化整个过程)。如果我在真实程序代码中的子例程write(*,*) "res in TIS2 =",res
中添加了TIS2
,则结果是正确的,但这是不希望的(特别是由于速度降低)。
我已经测试了各种编译器标志组合;即以下内容:
/ debug:full / O2 / Qinit:snan / Qinit:arrays / fpe:0 / Qipo / traceback / check:uninit / arch:SSE3 / real_size:64 / fp:fast = 2 / Qvec阈值:60 /递归
有人对此有任何提示或评论吗?
答案 0 :(得分:0)
我犯了一个错误(错误),其中数组未完全正确填充。我在调试模式下使用了编译器标志/Qinit:snan
和/Qinit:arrays
来找到它。它没有在发布模式下显示。
因此,总的来说,这只是我代码中一个非常简单的错误,没有引起注意,大多数情况下(在99%的情况下)一切都很好,但并非总是如此。奇怪的是它没有处于释放模式。