在FORTRAN 77中调用子程序中的子程序时如何解决分段错误?

时间:2015-11-17 18:03:51

标签: segmentation-fault fortran subroutine fortran77

我几个月来一直在FORTRAN 77中遇到分段故障问题,我真的无法弄清楚我错在哪里。我是Fortran的新手。

我正在编写一个程序(main),我在其中调用子程序(source)。该子程序执行4阶Runge-Kutta方法(由Press,Teukolsky,Vetterling,Flannery在 Numerical Recipes in Fortran 77 中提出)来求解微分方程并从瞬间推进某些输入数据值到下一个。

为了执行Runge-Kutta方法,在source中调用另一个子例程deriv,它在数值上计算微分方程中的导数。对于Runge-Kutta方法,子例程deriv必须被调用四次,我必须在x和y两个方向上执行数据值:因此,全局地,deriv被调用八次source

通过Runge-Kutta前进的值被收集到最大大小mxnn=200000的矢量(param.fi中包含的参数),但在程序的过程中只有一部分(大小) nodes)将被填补并且如此先进。这些向量传递给source,它们的组件传递给deriv以获得Runge-Kutta方法。

这是main的摘录(这是一个非常重要的节目,因此我已经删除了我认为不必要的内容):

      PROGRAM main

      INCLUDE 'param.fi'

      INTEGER nodes
      DOUBLEPRECISION z0
      DOUBLEPRECISION deltaxnp1(mxnn),zxnp1(mxnn),u0xnp1(mxnn)
      DOUBLEPRECISION deltaynp1(mxnn),zynp1(mxnn),u0ynp1(mxnn)
      DOUBLEPRECISION deltaxn(mxnn),zxn(mxnn),u0xn(mxnn)
      DOUBLEPRECISION deltayn(mxnn),zyn(mxnn),u0yn(mxnn)

      ...
      ...

      CALL source(nodes,                                  
     +        z0,deltaxn,u0xnp1,u0xn,zxn,zxnp1,deltaxnp1,
     +        deltayn,u0ynp1,u0yn,zyn,zynp1,deltaynp1,
     +        [...])

      ...
      ...

      END program main

这是我在不同模块中编写的子程序source

      SUBROUTINE source(nodes,
     +     z0,deltaxin,u0xnew,u0xin,zx,zxout,deltaxout,
     +     deltayin,u0ynew,u0yin,zy,zyout,deltayout,
     +     [...])

      INTEGER nodes, i
      DOUBLEPRECISION z0
      DOUBLEPRECISION deltaxin(*),u0xnew(*),u0xin(*)
      DOUBLEPRECISION zx(*), zxout(*),deltaxout(*)
      DOUBLEPRECISION deltayin(*),u0ynew(*)
      DOUBLEPRECISION u0yin(*),zy(*),zyout(*),deltayout(*)
      DOUBLEPRECISION duxdt(mxnn),duydt(mxnn)

*** Variables needed for Runge-Kutta ***
      DOUBLEPRECISION dtmezzo,d6,th
      DOUBLEPRECISION dzini(mxnn),dzt(mxnn),dzm(mxnn)
      DOUBLEPRECISION zt(mxnn)

      DO i=1,nodes

      ...

         dtmezzo=dt*0.5D0      
         d6=dt/6.D0                                        
         th = time + dtmezzo

*** Runge-Kutta for values in x direction
*** INPUT: zx(i)         
*** OUTPUT: zxout(i)

         CALL deriv(zx(i),u0xnew(i),z0,duxdt(i),dzini(i))
         zt(i)=zx(i)+dtmezzo*dzini(i)

         CALL deriv(zt(i),u0xnew(i),z0,duxdt(i),dzt(i))            
         zt(i)=zx(i)+dtmezzo*dzt(i)

         CALL deriv(zt(i),u0xnew(i),z0,duxdt(i),dzm(i))
         zt(i)=zx(i)+dt*dzm(i)
         dzm(i)=dzt(i)+dzm(i)

         CALL deriv(zt(i),u0xnew(i),z0,duxdt(i),dzt(i))
         zxout(i)=zx(i)+t6*(dzini(i)+dzt(i)+2.*dzm(i))

*** Runge-Kutta for values in y direction
*** INPUT: zy(i)         
*** OUTPUT: zyout(i)

         CALL deriv(zy(i),u0ynew(i),z0,duydt(i),dzini(i))   !!!!!
         zt(i)=zy(i)+dtmezzo*dzyini(i)

         CALL deriv(zt(i),u0ynew(i),z0,duydt(i),dzt(i))            
         zt(i)=zy(i)+dtmezzo*dzyt(i)

         CALL deriv(zt(i),u0ynew(i),z0,duydt(i),dzm(i))
         zt(i)=zy(i)+dt*dzm(i)
         dzm(i)=dzt(i)+dzm(i)

         CALL deriv(zt(i),u0ynew(i),z0,duydt(i),dzt(i))
         zyout(i)=zy(i)+t6*(dzini(i)+dzt(i)+2.*dzm(i))

         ...

      ENDDO

      RETURN
      END

这是子程序deriv

      SUBROUTINE deriv(Z,u0,z0,dudt,der)

      DOUBLEPRECISION Z,u0,z0,dudt,der

      der = ( (((0.4D0**2)*u0)/z0) - Z*(dexp(Z)-Z-1) 
     +         * (dudt/u0) ) / ( dexp(Z)*(Z-1)+1 )

      END

在编译程序时(使用GNUfortran),它没有给我带来任何问题:但是在运行程序后出现Segmentation fault (core dumped)错误并且程序中止。经过一些分析后,似乎问题在于我第一次为y方向的值调用deriv(即第五次调用,我在代码中用!!!!!标记)。

对我来说很奇怪,因为如果我尝试编译并运行程序而没有 y方向块(仅针对x方向解决Runge-Kutta)一切都很顺利。 deriv的形式在两个方向上完全相同:只有输入和输出发生变化。

我检查了数组维度,似乎没有任何错误(至少对我来说),我担心我的脚本中存在概念错误。我在Stack Overflow上找到了各种答案,但无济于事。

我考虑使用dbg-g标志进行调试,但该程序是通过makefile编写的,我无法找到如何使用该标志。

0 个答案:

没有答案