【问题标题】:Segmentation fault: why is it resolved in a mystery way?分段错误:为什么会以一种神秘的方式解决?
【发布时间】:2014-06-28 15:43:38
【问题描述】:

我的 Fortran 代码有问题。 所以,这是我的代码的两个版本:

      program test
      real*8 x1,x2,val,func,y
      x1 = 1.0
      x2 = 3.0
!     y = func(x1)

      call qgaus(func,x1,x2,val)
      write(*,*) 'answer', val

      end

      function func(x)
       real*8 func,x
       func = cos(x)
      end 

      SUBROUTINE qgaus(func,a,b,ss)
      REAL*8 a,b,ss,func
      EXTERNAL func
      INTEGER j
      REAL*8 dx,xm,xr,w(5),x(5)
      SAVE w,x
      DATA w/.2955242247,.2692667193,.2190863625,.1494513491,
     *.0666713443/
      DATA x/.1488743389,.4333953941,.6794095682,.8650633666,
     *.9739065285/
      xm=0.5*(b+a)
      xr=0.5*(b-a)
      ss=0
      do 11 j=1,5
        dx=xr*x(j)
        ss=ss+w(j)*(func(xm+dx)+func(xm-dx))

11    continue
      ss=xr*ss

      END

第二个版本是相同的代码,但第 5 行 (y = func(x1)) 没有注释。第一个版本显示分段错误,而第二个程序继续计算(函数集成)。具体来说,在第一种情况下,当子例程调用函数时会发生分段错误(我已经检查过了)。为什么会这样?为什么单独调用函数可以解决问题?我正在使用 GNU 编译器。 谢谢。

【问题讨论】:

    标签: function segmentation-fault fortran subroutine


    【解决方案1】:

    您使用了旧 Fortran 的一些非常糟糕的功能。学习使用implicit none,声明所有参数,最好学习 Fortran 90 及更高版本的标准,主要是模块和接口。还要学会使用编译器警告,因为gfortran可以识别错误:

    gfortran -fbacktrace -fcheck=all -Wall -g t1.f90 
    t1.f90:8.12:
    
     call qgaus(func,x1,x2,val)
                1
    Warning: Expected a procedure for argument 'func' at (1)
    

    子程序qgaus 需要一个函数作为参数。

    当你这样做时

    real*8 x1,x2,val,func,y
      x1 = 1.0
      x2 = 3.0
    
     call qgaus(func,x1,x2,val)
    

    那么func是一个实数,不是一个函数,程序一定会失败。

    添加时

    y = func(x1)
    

    编译器认为它是一个函数,因为你是这样调用它的。它将假定它是一个外部函数。

    最简单的解决方法是将func 声明为external,但更好的是阅读我的答案的第一段并正确定义所有变量并为过程使用显式接口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-02
      相关资源
      最近更新 更多