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.
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.