2012-08-01 101 views
0

我有一个Fortran数字代码从外部模块调用子例程。这段代码一直运行良好,直到我试图编译并在另一台机器上运行。在新机器上,我的程序崩溃很快。Fortran子程序返回失败

使用调试打印语句,我已经隔离了从外部子例程返回时发生崩溃。主程序多次调用子程序,从第二次调用返回到子程序(第一次调用工作正常)时发生崩溃。在使用这组输入数据时,它总是在第二个子例程调用时崩溃,但是使用另一组输入数据(大约是第一个的1/3)时,从第五个子例程调用返回时崩溃。

症状表明,每次都会有内存存储在内存中,并累积到每个子例程调用上,直到它耗尽空间,但我不确定那是什么或如何发生。该代码很难简化为一个最小工作示例,但我已经发布了下面的相关部分。让我知道是否有其他的东西可以帮助我们看到。它基本上是固定形式的Fortran 90

  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的对话框通知我的程序已停止工作。

+1

我的第一个想法是要绝对确定你传递给例程的实际值是双精度的,正如例程所要求的那样。更确切地说,确定例程想要在其dp参数中看到的字节大小(可能是8,但不一定是_),并确保它与传递的实参的字节大小相同。不同的编译器以不同的方式处理实数的精度。 – 2012-08-01 18:11:21

+0

@ bob.saveamento,我很确定他们是一样的,但是有内在的功能来检查字节大小吗? – astay13 2012-08-01 18:15:10

+0

当我想要这种信息时,我通常阅读编译器文档,但是您可以从“KIND”Fortran内部获取此信息。如果“r”是一个真实的* 8,那么kind(r)将返回8.或者,您可以通过编辑代码来双重确定,以便绝对指定实数的大小,即,而不是“真实”,用“真实(kind = 4)“,而不是”双精度“,用”real(kind = 8)“声明。 – 2012-08-01 18:27:01

回答

1

感谢大家在追逐这个问题上的帮助。我遵循M.S.B.'s suggestion并与-O2 -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck=all -fbacktrace编译。这揭示了我的子程序中包含的其他旧F77代码中的内存泄漏。显然有些内部数组声明的长度比需要的短1个项目。我修正了这个问题,现在一切都好了。