Segmentation Fault on Linux, but not on Windows

AI Thread Summary
The discussion centers around a segmentation fault encountered when running a Fortran program on Ubuntu (10.04 x64), which does not occur on Windows 7 (x64). The program, compiled with gfortran on both systems, initially failed due to undeclared variables in a subroutine, which led to the segmentation fault on Linux. The user highlights the importance of testing programs across different operating systems and compilers, as discrepancies can arise from non-standard library functions or variable declarations. The conversation also touches on the INTENT property of subroutine variables in Fortran, which can prevent such errors by enforcing variable usage rules. The user acknowledges the utility of this feature, recognizing that it could help avoid segmentation faults in the future. The discussion concludes with a light-hearted note on the nature of library functions and the user's past coding experiences.
LucasCampos
Messages
17
Reaction score
0
When I run a program on Ubuntu (10.04 x64) I receive a warning of segmentation fault. But when on windows (seven, x64), I do not receive this error. This program was compiled with gfortran on both systems. Any ideas why?

Code:
Program Lennard
Implicit None 
Double Precision sigma,e,dt,fx,fy,xi,yi,axi,ayi,fxmid,fymid,xmidi,&
ymidi,axmidi,aymidi,teti,omegi,tori,ineri,radi,massi,xj,yj,axj,&
ayj,xmidj,ymidj,axmidj,aymidj,tetj,omegj,torj,&
inerj,radj,massj,vxi,vyi,vxmidi,vymidi,vxj,vyj,vxmidj,vymidj,alfi,alfj,t
Integer counter,nshow
Call Opener
Call Inserter_General (dt,sigma,e)
Call Inserter_i (massi,radi,vyi,vxi,yi,xi,omegi,teti)
Call Inserter_j (massj,radj,vyj,vxj,yj,xj,omegj,tetj)
counter=0
ineri=0.5D0*massi*radi**2
inerj=0.5D0*massj*radj**2
Call Euler (sigma,e,dt,fx,fy,xi,yi,axi,ayi,fxmid,fymid,xmidi,&
ymidi,axmidi,aymidi,teti,omegi,tori,ineri,radi,massi,xj,yj,axj,&
ayj,xmidj,ymidj,axmidj,aymidj,tetj,omegj,torj,&
inerj,radj,massj,vxi,vyi,vxmidi,vymidi,vxj,vyj,vxmidj,vymidj,alfi,alfj,&
t)
End

Subroutine Inserter_General (dt,sigma,e)
Implicit None
Double Precision dt,sigma,e
Integer nshow
Write (*,*) 'Insert time step'
Read (*,*) dt
Write (*,*) 'Insert sigma'
Read (*,*) sigma
Write (*,*) 'Insert épislon'
Read (*,*) e
Write (*,*) 'Insert steps between output'
Read (*,*) nshow
End

Subroutine Inserter_i (massi,radi,vyi,vxi,yi,xi,omegi,teti)
Implicit None
Double Precision massi,radi,vyi,vxi,yi,xi,omegi,teti
Write (*,*) "Insert first disk's mass" 
Read (*,*) massi
Write (*,*) "Insert first disk's radius"
Read (*,*) radi
Write (*,*) "Insert first disk's inicial vertical speed"
Read (*,*) vyi
Write (*,*) "Insert first disk's inicial horizontal speed"
Read (*,*) vxi
Write (*,*) "Insert first disk's initial vertical position"
Read (*,*) yi
Write (*,*) "Insert first disk's initial horizontal position"
Read (*,*) xi
Write (*,*) "Insert first disk's initial angular speed"
Read (*,*) omegi
Write (*,*) "Insert first disk's initial angular position" 
Read (*,*) teti
End

Subroutine Inserter_j (massj,radj,vyj,vxj,yj,xj,omegj,tetj)
Implicit None
Double Precision massj,radj,vyj,vxj,yj,xj,omegj,tetj
Write (*,*) "Insert second disk's mass" 
Read (*,*) massj
Write (*,*) "Insert second disk's radius"
Read (*,*) radj
Write (*,*) "Insert second disk's inicial vertical speed"
Read (*,*) vyj
Write (*,*) "Insert second disk's inicial horizontal speed"
Read (*,*) vxj
Write (*,*) "Insert second disk's initial vertical position"
Read (*,*) yj
Write (*,*) "Insert second disk's initial horizontal position"
Read (*,*) xj
Write (*,*) "Insert second disk's initial angular speed"
Read (*,*) omegj
Write (*,*) "Insert second disk's initial angular position" 
Read (*,*) tetj
End

Subroutine Force (fx,fy,xi,yi,axi,ayi,fxmid,fymid,xmidi,ymidi,axmidi,&
aymidi,radi,massi,xj,yj,axj,ayj,xmidj,ymidj,axmidj,aymidj,radj,massj,&
vxi,vyi,vxmidi,vymidi,vxj,vyj,vxmidj,vymidj,e,sigma,dt)
Implicit None
Double Precision fx,fy,xi,yi,axi,ayi,fxmid,fymid,xmidi,ymidi,axmidi,&
aymidi,radi,massi,xj,yj,axj,ayj,xmidj,ymidj,axmidj,aymidj,radj,massj,&
vxi,vyi,vxmidi,vymidi,vxj,vyj,vxmidj,vymidj,e,sigma,dt
fx=4*e*(12*((sigma**12)/(abs(xi-xj)**13))-(6*(sigma**6)/(abs(xi-xj)**7)))
fy=4*e*(((sigma**12)/(abs(yi-yj)**13))-((sigma**6)/(abs(yi-yj)**7)))
IF(xj .GT. xj) axi=fx/massi
IF(xj .GT. xj) axj=-fx/massj
IF(yj .GT. yj) ayi=fy/massi
IF(yj .GT. yj) ayj=-fy/massj
IF(xj .LE. xj) axi=-fx/massi
IF(xj .LE. xj) axj=fx/massj
IF(yj .LE. yj) ayi=-fy/massi
IF(yj .LE. yj) ayj=fy/massj
vxmidi=vxi+axi*(dt/2)
xmidi=xi+vxi*(dt/2)
vymidi=vyi+ayi*(dt/2)
ymidi=yi+vyi*(dt/2)
vxmidj=vxj+axj*(dt/2)
xmidj=xj+vxj*(dt/2)
vymidj=vyj+ayj*(dt/2)
ymidj=yj+vyj*(dt/2)
fxmid=4*e*(((sigma**12)/(abs(xmidi-xmidj)**13))-((sigma**6)/&
(abs(xmidi-xmidj)**7)))
fymid=4*e*(((sigma**12)/(abs(ymidi-ymidj)**13))-((sigma**6)/&
(abs(ymidi-ymidj)**7)))
!
IF(xmidj .GT. xmidj) axmidi=fxmid/massi
IF(xmidj .GT. xmidj) axmidj=-fxmid/massj
IF(ymidj .GT. ymidj) aymidi=fymid/massi
IF(ymidj .GT. ymidj) aymidj=-fymid/massj
!
IF(xmidj .LE. xmidj) axmidi=-fxmid/massi
IF(xmidj .LE. xmidj) axmidj=fxmid/massj
IF(ymidj .LE. ymidj) aymidi=-fymid/massi
IF(ymidj .LE. ymidj) aymidj=fymid/massj
!
End

Subroutine EulerTransI (vxi,xi,vyi,yi,axmidi,vxmidi,aymidi,vymidi,dt) 
Implicit None
Double Precision vxi,xi,vyi,yi,axmidi,vxmidi,aymidi,vymidi,dt
vxi=vxi+axmidi*dt
xi=xi+vxmidi*dt
vyi=vyi+aymidi*dt
yi=yi+vymidi*dt
End

Subroutine EulerTransJ (vxj,xj,vyj,yj,axmidj,vxmidj,aymidj,vymidj,dt)
Implicit None
Double Precision vxj,xj,vyj,yj,axmidj,vxmidj,aymidj,vymidj,dt
vxj=vxj+axmidj*dt
xj=xj+vxmidj*dt
vyj=vyj+aymidj*dt
yj=yj+vymidj*dt
End

Subroutine Torque (xmidi,xmidj,ymidi,ymidj,fxmid,fymid,tori,torj,teti,&
tetj,radi,radj,ineri,inerj,alfi,alfj)
Implicit None
Double Precision xmidi,xmidj,ymidi,ymidj,fxmid,fymid,tori,torj,teti,&
tetj,radi,radj,ineri,inerj,alfi,alfj
IF(xmidj .LE. xmidj) fxmid=-fxmid
IF(ymidj .LE. ymidj) fymid=-fymid
!
tori=radi*((fymid*cos(teti))-(fxmid*sin(teti)))
torj=-radj*((fymid*cos(tetj))-(fxmid*sin(tetj)))
alfi=tori/ineri
alfj=torj/inerj
End

Subroutine EulerRotI (omegi,alfi,teti,dt)
Implicit None 
Double Precision omegi,alfi,teti,dt
omegi=omegi+alfi*dt
teti=teti+omegi*dt
End

Subroutine EulerRotJ (omegj,alfj,tetj,dt)
Implicit None 
Double Precision omegj,alfj,tetj,dt
omegj=omegj+alfj*dt
tetj=tetj+omegj*dt
End

Subroutine Euler (sigma,e,dt,fx,fy,xi,yi,axi,ayi,fxmid,fymid,xmidi,&
ymidi,axmidi,aymidi,teti,omegi,tori,ineri,radi,massi,xj,yj,axj,&
ayj,xmidj,ymidj,axmidj,aymidj,tetj,omegj,torj,&
inerj,radj,massj,vxi,vyi,vxmidi,vymidi,vxj,vyj,vxmidj,vymidj,alfi,alfj,&
t)
Implicit None 
Double Precision sigma,e,dt,fx,fy,xi,yi,axi,ayi,fxmid,fymid,xmidi,&
ymidi,axmidi,aymidi,teti,omegi,tori,ineri,radi,massi,xj,yj,axj,&
ayj,xmidj,ymidj,axmidj,aymidj,tetj,omegj,torj,&
inerj,radj,massj,vxi,vyi,vxmidi,vymidi,vxj,vyj,vxmidj,vymidj,alfi,alfj,t
Integer counter,nshow
!
100 Call Force (fx,fy,xi,yi,axi,ayi,fxmid,fymid,xmidi,ymidi,axmidi,&
aymidi,radi,massi,xj,yj,axj,ayj,xmidj,ymidj,axmidj,aymidj,radj,massj,&
vxi,vyi,vxmidi,vymidi,vxj,vyj,vxmidj,vymidj,e,sigma,dt)
Call EulerTransI (vxi,xi,vyi,yi,axmidi,vxmidi,aymidi,vymidi,dt)
Call EulerTransJ (vxj,xj,vyj,yj,axmidj,vxmidj,aymidj,vymidj,dt)
Call Torque (xmidi,xmidj,ymidi,ymidj,fxmid,fymid,tori,torj,teti,&
tetj,radi,radj,ineri,inerj,alfi,alfj) 
Call EulerRotI (omegi,alfi,teti,dt)
Call EulerRotJ (omegj,alfj,tetj,dt)
t=t+dt
counter=counter+1
Write (1,*) xi+cos(teti)*radi,yi+sin(teti)*radi
Write (2,*) xj+cos(tetj)*radj,yj+sin(tetj)*radj
If (mod(nshow,counter) .EQ. 0.0D0) Call Table (xi,yi,xj,yj)
Write (3,*) vxj,vyj,yj,xj
Write (3,*) axmidj,aymidj,axmidi,aymidi
If (t .GT. 900) Go to 200
Go to 100
200 Write (*,*) 'Done'
End

Subroutine Opener
Open (Unit=1,File="movi.dat")
Open (Unit=2,File="movj.dat")
Open (Unit=3,File="cmi.dat")
Open (Unit=4,File="cmj.dat")
End

Subroutine Table (xi,yi,xj,yj,teti,tetj,radi,radj)
Implicit None
Double Precision xi,yi,xj,yj,teti,tetj,radi,radj
Write (1,*) xi+cos(teti)*radi,yi+sin(teti)*radi
Write (2,*) xj+cos(tetj)*radj,yj+sin(tetj)*radj
Write (3,*) xi,yi
Write (4,*) xj,yj
End
 
Technology news on Phys.org
I've found the problem. It was on the Call Table. Not all variables used was declared. Just a small change and it all worked out.
 
This problem illustrates that it is a good idea to test your program on as many different machines and as many different compilers as you can get your hands on. Sometimes a program will work on a Windows machine but not on a Linux machine, sometimes the other way around as is the case here. Sometimes it will only work on a Mac, or only on a Sun. Sometimes your program won't even compile on other machines because you just happen to have used a non-standard library function. Unless you read the documentation carefully, it is not at all clear that the function in question is non-standard; ofttimes vendors won't even say that their spiffy little function is non-standard.
 
Indeed, it is a great idea. In this case, windows' version should not have worked. If I hadn't the linux problem, I would have never noticed my mistake. I'm not using libraries yet. But I guess it would that idea even better.
 
I'm curious as to how under the Windows system you were able to compile using undeclared variables by issuing IMPLICIT NONE. Oh well, as D H mentioned, I guess it's always better to try it on a few different platforms.
 
I could compile on both, Windows and Linux. I think gfortran didn't return errors because they are declared on the subroutine, but are not called. That's why the segfault. The subroutine was trying to access variables which it was not entitled to.
 
LucasCampos said:
The subroutine was trying to access variables which it was not entitled to.

Ah, are you familiar with the INTENT property of subroutine variables? e.g.
Code:
...
SUBROUTINE func_exp(x,n,y)
IMPLICIT NONE
REAL(kind=r_def),INTENT(IN) :: x !--incoming number, not allowed to be changed
INTEGER(kind=i_def),INTENT(IN) :: n !--ditto
REAL(kind=r_def),INTENT(OUT) :: y !--result of the subroutine

y = x**n

END SUBROUTINE

It's something I do for each subroutine. In times such as yours, you may get a nice pretty compiler error saying a variable has incorrect intent rather than the bane of us all...the seg fault.

p.s. There is also an INTENT(INOUT) which allows an incoming variable to be changed.
 
LucasCampos said:
I'm not using libraries yet.
Whether you know it or not, you most certainly are. Those calls to read, write, sin, cos -- those are library functions. You didn't write those functions, did you? Those functions reside in a library -- in this case they are a part of the library provided au gratis by the language.
 
minger said:
Ah, are you familiar with the INTENT property of subroutine variables? e.g.
Code:
...
SUBROUTINE func_exp(x,n,y)
IMPLICIT NONE
REAL(kind=r_def),INTENT(IN) :: x !--incoming number, not allowed to be changed
INTEGER(kind=i_def),INTENT(IN) :: n !--ditto
REAL(kind=r_def),INTENT(OUT) :: y !--result of the subroutine

y = x**n

END SUBROUTINE

It's something I do for each subroutine. In times such as yours, you may get a nice pretty compiler error saying a variable has incorrect intent rather than the bane of us all...the seg fault.

p.s. There is also an INTENT(INOUT) which allows an incoming variable to be changed.

No, I didn't know of this command. It seems quite interesting. And you right. Segfault is as scary as hell.

D H said:
Whether you know it or not, you most certainly are. Those calls to read, write, sin, cos -- those are library functions. You didn't write those functions, did you? Those functions reside in a library -- in this case they are a part of the library provided au gratis by the language.

I most certainly did! But I whispered some of my codes to some IBM guy and he stole from me. At least he spent three years trying to understand them. :approve:
 
Back
Top