Arrays Fortran子例程返回时失败
我有一个Fortran数字代码,可以从外部模块调用子程序。在我尝试在另一台机器上编译和运行之前,这段代码一直运行良好。在新机器上,我的程序崩溃得相当快 通过使用debug print语句,我发现崩溃发生在从外部子例程返回时。主程序多次调用子例程,在第二次调用子例程返回时发生崩溃(第一次调用工作正常)。它总是在使用这组输入数据的第二个子例程调用时崩溃,但在使用另一组输入数据(大约是第一组的1/3)时,它在从第五个子例程调用返回时崩溃 这些症状向我暗示,每次都有一些东西被存储在内存中,并在每次子例程调用中累积,直到它耗尽空间,但我不确定这是什么,也不确定它是如何发生的。代码很难简化为一个最小的工作示例,但我已经在下面发布了相关部分。如果有其他有助于了解的内容,请告诉我。它基本上是固定格式的Fortran 90Arrays Fortran子例程返回时失败,arrays,fortran,fortran90,Arrays,Fortran,Fortran90,我有一个Fortran数字代码,可以从外部模块调用子程序。在我尝试在另一台机器上编译和运行之前,这段代码一直运行良好。在新机器上,我的程序崩溃得相当快 通过使用debug print语句,我发现崩溃发生在从外部子例程返回时。主程序多次调用子例程,在第二次调用子例程返回时发生崩溃(第一次调用工作正常)。它总是在使用这组输入数据的第二个子例程调用时崩溃,但在使用另一组输入数据(大约是第一组的1/3)时,它在从第五个子例程调用返回时崩溃 这些症状向我暗示,每次都有一些东西被存储在内存中,并在每次子例程
use fd
implicit none
integer, parameter :: ms = 2000
integer n
real(dp), dimension(ms) :: s
real(dp), dimension(ms) :: e
real(dp), dimension(ms) :: f
real(dp), dimension(ms) :: d1f
real(dp), dimension(ms) :: d2f
real(dp), dimension(ms) :: c, d
real(dp), dimension(ms) :: a
real(dp), dimension(ms) :: b
real(dp), dimension(ms) :: temp
integer w
integer k
real(dp) th
do i = 1,n
temp(i) = a(i)
end do
call lprsmf(s(1:n),temp(1:n),n,w,k,th,a(1:n),d1f(1:n),
* d2f(1:n))
do i = 1,n
temp(i) = b(i)
end do
call lprsmf(s(1:n),temp(1:n),n,w,k,th,b(1:n),d1f(1:n),
* d2f(1:n))
do i = 1,n
temp(i) = c(i)
end do
call lprsmf(s(1:n),temp(1:n),n,w,k,th,c(1:n),d1f(1:n),
* d2f(1:n))
do i = 1,n
temp(i) = d(i)
end do
call lprsmf(s(1:n),temp(1:n),n,w,k,th,d(1:n),d1f(1:n),
* d2f(1:n))
do i = 1,n
temp(i) = e(i)
end do
call lprsmf(s(1:n),temp(1:n),n,w,k,th,e(1:n),d1f(1:n),
* d2f(1:n))
do i = 1,n
temp(i) = f(i)
end do
call lprsmf(s(1:n),temp(1:n),n,w,k,th,f(1:n),d1f(1:n),
* d2f(1:n))
模块fd
:
module fd
! Double precision real kind
integer, parameter :: dp = selected_real_kind(15)
contains
subroutine lprsmf(x,y,n,w,k,th,s,d1,d2)
! INPUTS:
! x, y, n, w, k, th
! OUTPUTS:
! s, d1, d2
implicit none
real(dp), dimension(n) :: x,y,s,d1,d2
integer n,w,k
real(dp) th
! ... code here ...
end subroutine lprsmf
end module fd
我的编译器是gfortran 4.6.1。除了让代码停止崩溃之外,我真的很想了解参数传递的基本情况(因为我假设问题在于从程序中传递数组片段)。请注意,a、b、c、d、e、f、s、temp、d1f、d2f
的长度为2000,而表示有效数据范围的n
的长度为100-500,具体取决于输入数据的长度
编辑:错误消息是Windows弹出一个对话框,通知我程序已停止工作。感谢所有人帮助解决此问题。我遵循并编译了
-O2-fimplicit none-Wall-Wline truncation-Wcharacter truncation-Wsurprising-Waliasing-Wimplicit interface-Wunused参数-fwhole file-fcheck=all-fbacktrace
。这揭示了我在子程序中包含的其他人的旧F77代码中存在内存泄漏。显然,某些内部数组的长度比需要的长度短1项。我解决了这个问题,现在一切似乎都正常了。我的第一个想法是绝对确定你传递给例程的real确实是双精度的,正如例程所要求的那样。更准确地说,确保例程希望在其dp参数中看到什么字节大小(可能是8,但不一定),并确保与传递的实际参数的字节大小相同。不同的编译器处理实数的精度不同。好的,如果您确定所有声明都是100%一致的,那么精度不是问题。我能想到的另一件事是分割错误。很多时候,故障点与代码中的bug实际所在的位置无关。我发现导致seq错误的两个最常见的原因是写入超出了数组的界限,而且输入参数列表与子例程期望的输入变量类型之间不匹配(听起来不像是坏记录)。您可以通过使用数组边界检查进行编译来跟踪前者。您正在“使用”包含子例程lprsmf的模块,该模块来自调用它的程序?使用gfortran尝试最大限度的调试选项,例如:-O2-fimplicit none-Wall-Wline truncation-Wcharacter truncation-Wsurprising-Waliasing-Wimplicit interface-Wunused parameter-fwhole file-fcheck=all-fbacktraceHi,您能用程序崩溃时收到的实际错误消息更新您的问题吗,这是一个错误吗?我肯定要做的第一件事是遵循M.S.B.的建议,或者至少使用'-fcheck=bounds'(使用gfortran)。至于do循环,我认为它们是等效的。关于n
的价值,我的观点是,您没有给我们提供一个[简短、自包含的代码示例](sscce.org/),这使得我们很难追踪到底发生了什么。你能用一个复制错误的最小完整程序更新你的问题吗?