Search code examples
functionsegmentation-faultfortransubroutine

Segmentation fault: why is it resolved in a mystery way?


I have a problem with my Fortran code. So, here is two versions of my code:

      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

The second version is the same code but line 5 (y = func(x1)) is not commented.The first version shows me segmentation fault while the second program proceeds the calculations (integration of function) . To be specific, in the first case segmentation fault occurs when the subroutine calls the function ( I've checked it). Why does it happen? Why calling the function separately solves the problem? I am using GNU compiler. Thanks.


Solution

  • You use some really bad features of old Fortran. Learn to use implicit none, declare all arguments and preferably learn Fortran 90 and later standards, mainly modules and interfaces. Also learn to use compiler warnings, because gfortran can identify the error:

    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)
    

    Subroutine qgaus needs a function as an argument.

    When you do

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

    then func is a real number, not a function, and the program must fail.

    When you add

    y = func(x1)
    

    the compiler sees it is a function, because you are calling it that way. It will assume it is an external function.

    The simplest fix is to declare func as external, but better is to read the first paragraph of my answer and properly define all variables and use explicit interfaces for procedures.