Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Fortran mex *fine* with win 32, OSX 32 and OSX 64, but Segmentation Errors with Linux 64....

Subject: Fortran mex *fine* with win 32, OSX 32 and OSX 64, but Segmentation Errors with Linux 64....

From: Arwel

Date: 29 Nov, 2012 15:00:13

Message: 1 of 4

Hi,
I have a Fortran mex file that has been running fine on OSX 64 bit or 32 bit, and also on 32 bit Windows. However, I've tried compiling it on Linux (using gfortran 4.3 or 4.4), and it crashes with a segmentation error. I'm at a total loss at the moment, because surely if there was a problem with 32/64 bit variable types etc, then it would have crashed on the 64 bit mac too??

Can anyone help, and see any obvious mistakes in the code?? I'm really a Linux newbie and I'm really lost here...



#include "fintrf.h"

C=======================================================================
C Abeles Calculation for Matlab
C
C out = abeles(xdata,sld,nbair,nbsub,ssub,repeats,s_between_repeats,resol)
C
C=======================================================================

      subroutine mexfunction(nlhs, plhs, nrhs, prhs)

C-----------------------------------------------------------------------
C
      mwpointer plhs(*), prhs(*)
      mwpointer mxGetPr, mxCreateDoubleMatrix
      mwpointer x_pr, y_pr
C-----------------------------------------------------------------------
C
      integer pr_in, pr_in2, pr_in3, pr_in4, pr_in5, pr_in6, pr_in7
integer pr_out, pr_in8
      mwsize mxGetM, mxGetN
      mwsize m_in_q, n_in_q, points, layers
mwsize m_in_sld, n_in_sld

      if(nrhs .ne. 8) then
         call mexErrMsgTxt('8 inputs required to Abeles.')
      endif
      if(nlhs .gt. 1) then
         call mexErrMsgTxt('Less than one output required to Abeles.')
      endif

 
! work out points
      m_in_q = mxGetM(prhs(1))
      n_in_q = mxGetN(prhs(1))
if (n_in_q .gt. 1) then
call mexErrMsgTxt('Qz needs to be a column vector')
endif
      points = m_in_q

! do the same for layers
      m_in_sld = mxGetM(prhs(2))
      n_in_sld = mxGetN(prhs(2))
if (n_in_sld .ne. 3) then
call mexErrMsgTxt('SLD needs three columns: d r s')
endif
      layers = m_in_sld


      pr_in = mxGetPr(prhs(1))
pr_in2 = mxGetPr(prhs(2))
pr_in3 = mxGetPr(prhs(3))
pr_in4 = mxGetPr(prhs(4))
pr_in5 = mxGetPr(prhs(5))
pr_in6 = mxGetPr(prhs(6))
pr_in7 = mxGetPr(prhs(7))
pr_in8 = mxGetPr(prhs(8))

      plhs(1) = mxCreateDoubleMatrix(m_in_q, n_in_q, 0)
      pr_out = mxGetPr(plhs(1))

C Call the computational routine.
      call comp(%val(pr_out),%val(pr_in),%val(pr_in2),%val(pr_in3),
     + %val(pr_in4),%val(pr_in5),%val(pr_in6),
     + %val(pr_in7),%val(pr_in8),layers,points)
        

      return
      end



C=========================================================================
c
C computational routine.....
C
C=========================================================================

      subroutine comp(out,x,sld,nbair,nbsub,ssub,nrepeats,resType,
     + resol,layers,points)
      integer size, i
integer layers,points,j,reploop, nl, loop, nrepeats
double complex c0 , c1 , ci , beta , rij , N , M , MI , rimaj
double complex blast , num , den , quo
double complex pimag , pair , psub , plast
real*8 pi , twopi , lam , ilow, ihi
real*8 thick , q , theta, rho, rough, resol
real*8 preal , snair , snsub , snlay, rfac, resType
real*8 out(points,1),x(points,1),sld(layers,3),nbair,nbsub,ssub
real*8 dummydata(points,1), g(points,1)
dimension N(2,2) , M(2,2) , MI(2,2)

c0 = Dcmplx(0 , 0)
c1 = Dcmplx(1 , 0)
ci = Dcmplx(0 , 1)
lam = 4.5
pi = 3.141592653589
rfac = ((4*pi)*(4*pi))/2
twopi = 2*pi
snair = (1.0 - dble(nbair*((lam*lam) / twopi)))
snsub = (1.0 - dble(nbsub*((lam*lam) / twopi)))


do loop = 1 , points
q = x(loop,1)
theta = asin(q*lam / (4*pi))
preal = ((snsub)*(snsub)) - ((snair)*(snair))*(cos(theta)**2)
psub = cdsqrt(preal*c1)
pair = snair*sin(theta)*c1
plast = pair
blast = 0.0
rlast = sld(1,3)
MI(1 , 1) = c1
MI(2 , 2) = c1
MI(1 , 2) = c0
MI(2 , 1) = c0
do reploop = 1, nrepeats
do nl = 1 , 3
thick = 1000
rho = 20e-6
rough = 1


snlay = (1 - dble(rho*((lam*lam) / twopi)))
preal = (snlay*snlay) - (snair*snair) *cos(theta)**2
pimag = cdsqrt(preal*c1)
beta = (twopi / lam)*thick*pimag
rij = dcmplx(plast - pimag) / dcmplx(plast + pimag)
rij = rij * cdexp(-rfac*plast*pimag*(rough*rough)/(lam*lam))
N(1 , 1) = cdexp(blast*ci)
N(2 , 1) = rij * cdexp( - blast*ci)
N(2 , 2) = cdexp( - blast*ci)
N(1 , 2) = rij * cdexp(blast*ci)
plast = pimag
blast = beta
rlast = rough
call mcopy(MI , M)
call mmult(M , N , MI)
end do
end do
rij = (dcmplx(plast - psub)) / (dcmplx(plast + psub))
rij = rij * cdexp(-rfac*plast*psub*(ssub*ssub)/(lam*lam))
N(1 , 1) = cdexp(blast*ci)
N(2 , 1) = rij*cdexp( - blast*ci)
N(2 , 2) = cdexp( - blast*ci)
N(1 , 2) = rij*cdexp(blast*ci)
call mcopy(MI , M)
call mmult(M , N , MI)
num = MI(2 , 1)*dconjg(MI(2 , 1))
den = MI(1 , 1)*dconjg(MI(1 , 1))
call cdiv(num , den , quo)
out(loop,1) = quo
end

return
end subroutine
 

! ----- -----------------------------
SUBROUTINE CDIV(NUM , DEN , QUO)
! SUBROUTINE TO DIVIDE COMPLEX NUMBERS
! AND TRAP DIVIDE CHECKS
double COMPLEX NUM , DEN , QUO , C1 , C0
C1 = DCMPLX(1.0 , 0.0)
C0 = DCMPLX(0.0 , 0.0)
IF(DEN.EQ.NUM)THEN
QUO = C1
RETURN
ENDIF
IF(DEN.EQ.C0 )THEN
QUO = C0
RETURN
ENDIF
QUO = NUM / DEN
RETURN
END SUBROUTINE
! ----- -------------------------------------------
SUBROUTINE MMULT(A1 , A2 , A3)
! SUBROUTINE FOR MATRIX MUTIPLICATION
DOUBLE COMPLEX A1(2 , 2) , A2(2 , 2) , A3(2 , 2)
A3(1 , 1) = A1(1 , 1)*A2(1 , 1) + A1(1 , 2)*A2(2 , 1)
A3(1 , 2) = A1(1 , 1)*A2(1 , 2) + A1(1 , 2)*A2(2 , 2)
A3(2 , 1) = A1(2 , 1)*A2(1 , 1) + A1(2 , 2)*A2(2 , 1)
A3(2 , 2) = A1(2 , 1)*A2(1 , 2) + A1(2 , 2)*A2(2 , 2)
RETURN
END
SUBROUTINE MCOPY(A1 , A2)
! SUBROUTINE TO COPY A MATRIX
DOUBLE COMPLEX A1(2 , 2) , A2(2 , 2)
A2(1 , 1) = A1(1 , 1)
A2(1 , 2) = A1(1 , 2)
A2(2 , 1) = A1(2 , 1)
A2(2 , 2) = A1(2 , 2)
RETURN
END SUBROUTINE

Subject: Fortran mex *fine* with win 32, OSX 32 and OSX 64, but Segmentation Errors with Linux 64....

From: James Tursa

Date: 29 Nov, 2012 18:53:16

Message: 2 of 4

"Arwel " <a.v.hughes@rl.ac.uk> wrote in message <k97t9t$5m9$1@newscl01ah.mathworks.com>...
> Hi,
> I have a Fortran mex file that has been running fine on OSX 64 bit or 32 bit, and also on 32 bit Windows. However, I've tried compiling it on Linux (using gfortran 4.3 or 4.4), and it crashes with a segmentation error. I'm at a total loss at the moment, because surely if there was a problem with 32/64 bit variable types etc, then it would have crashed on the 64 bit mac too??
>
> Can anyone help, and see any obvious mistakes in the code?? I'm really a Linux newbie and I'm really lost here...

(snip)

> integer pr_in, pr_in2, pr_in3, pr_in4, pr_in5, pr_in6, pr_in7
> integer pr_out, pr_in8

Variables that hold addresses in Fortran should *always* be declared as mwpointer, not integer as above. The default integer data type in Fortran is often a 32-bit integer, even on 64-bit systems.

(snip)

> pr_in = mxGetPr(prhs(1))
> pr_in2 = mxGetPr(prhs(2))
> pr_in3 = mxGetPr(prhs(3))
> pr_in4 = mxGetPr(prhs(4))
> pr_in5 = mxGetPr(prhs(5))
> pr_in6 = mxGetPr(prhs(6))
> pr_in7 = mxGetPr(prhs(7))
> pr_in8 = mxGetPr(prhs(8))
>
> plhs(1) = mxCreateDoubleMatrix(m_in_q, n_in_q, 0)
> pr_out = mxGetPr(plhs(1))
>
> C Call the computational routine.
> call comp(%val(pr_out),%val(pr_in),%val(pr_in2),%val(pr_in3),
> + %val(pr_in4),%val(pr_in5),%val(pr_in6),
> + %val(pr_in7),%val(pr_in8),layers,points)

When you get to the above call, if the default integer is 32-bit then the %val(pr_out) etc stuff will put a 32-bit value on the stack when the called routine comp is expecting a 64-bit address. This will bomb. Frankly, I am surprised this ever worked on a 64-bit system, because the default integer would have needed to be 64-bit. Maybe on one compiler it is and on another compiler it isn't, or maybe there are compilation flags in use to force it one way or the other. You might print out the result of kind(pr_out) to check the size of a default integer.

In any event, you should change *all* types for variables that are holding addresses to be mwpointer. E.g.,

       mwpointer pr_in, pr_in2, pr_in3, pr_in4, pr_in5, pr_in6, pr_in7
  mwpointer pr_out, pr_in8


James Tursa

Subject: Fortran mex *fine* with win 32, OSX 32 and OSX 64, but Segmentation Errors with Linux 64....

From: James Tursa

Date: 29 Nov, 2012 19:01:15

Message: 3 of 4

"Arwel " <a.v.hughes@rl.ac.uk> wrote in message <k97t9t$5m9$1@newscl01ah.mathworks.com>...
> Hi,
> I have a Fortran mex file that has been running fine on OSX 64 bit or 32 bit, and also on 32 bit Windows. However, I've tried compiling it on Linux (using gfortran 4.3 or 4.4), and it crashes with a segmentation error. I'm at a total loss at the moment, because surely if there was a problem with 32/64 bit variable types etc, then it would have crashed on the 64 bit mac too??
>
> Can anyone help, and see any obvious mistakes in the code?? I'm really a Linux newbie and I'm really lost here...

(snip)

Another potential problem. In the calling routine you have this:

> mwsize m_in_q, n_in_q, points, layers

mwsize might be 32-bit or 64-bit depending on compiling flags.

(snip)

> call comp(%val(pr_out),%val(pr_in),%val(pr_in2),%val(pr_in3),
> + %val(pr_in4),%val(pr_in5),%val(pr_in6),
> + %val(pr_in7),%val(pr_in8),layers,points)

You then pass layers and points to comp above.

(snip)

> subroutine comp(out,x,sld,nbair,nbsub,ssub,nrepeats,resType,
> + resol,layers,points)
> integer size, i
> integer layers,points,j,reploop, nl, loop, nrepeats

Then in comp layers and points are delcared as integer, which again could be 32-bit or 64-bit depending on compiler and compiling flags.

It is possible that mwsize will not match integer (one 32-bit and one 64-bit), in which case things might bomb.

It is best to keep the declarations exactly the same in both routines. Either both default integer or both mwsize.

James Tursa

Subject: Fortran mex *fine* with win 32, OSX 32 and OSX 64, but Segmentation Errors with Linux 64....

From: Arwel

Date: 30 Nov, 2012 20:27:08

Message: 4 of 4

Thanks James. Actually, as you suggest, it really has to be some compiler (or even Matlab version??) specific flags that are dealing with the mis-mstches in different ways. The code compiles and runs fine under OSX 64 bit with gcc (4.2 maybe?? Apologies I'm away from my computers for this post so don't have the exact details...) with R2010a (I think...etc). But not on the Linux box I tried which is a Red Hat variant running 2011<something> with GCC 4.3 or 4.4 (tried both). However, I sent it to a friend of mine who is running an Ubuntu variant with 2012a, and that compiled and ran fine..again I don't know what compiler he was using. But interestingly he sent me the binary it produced and that then works fine on the Linux box I've been trying. So, the most obvious answer is that there are compiler specific settings that deal with mis-matches in this way, and once compiled it's happy.

Thanks very much for your suggestions though, and when I get a chance I'll play around with this a bit more. But, one question though... when you say "It is best to keep the declarations exactly the same in both routines. Either both default integer or both mwsize.", do you mean I should define layers points etc etc as mwsize in the 'comp' routine too?? The reason I ask is that they were all originally reals in the the comp routine, but then the more recent gfortran was chucking a load of warnings at me because I was using non-integers as loop counters, and apparently that's not the way to do things these days! So I just changed them all to integers to shut the warnings up. Anyway, thanks very much for your help, and when I get time to play some more I'll post anything interesting I find. But for now, my code runs, which is the main thing!

Cheers,
Arwel
















"James Tursa" wrote in message <k98bdr$nvu$1@newscl01ah.mathworks.com>...
> "Arwel " <a.v.hughes@rl.ac.uk> wrote in message <k97t9t$5m9$1@newscl01ah.mathworks.com>...
> > Hi,
> > I have a Fortran mex file that has been running fine on OSX 64 bit or 32 bit, and also on 32 bit Windows. However, I've tried compiling it on Linux (using gfortran 4.3 or 4.4), and it crashes with a segmentation error. I'm at a total loss at the moment, because surely if there was a problem with 32/64 bit variable types etc, then it would have crashed on the 64 bit mac too??
> >
> > Can anyone help, and see any obvious mistakes in the code?? I'm really a Linux newbie and I'm really lost here...
>
> (snip)
>
> Another potential problem. In the calling routine you have this:
>
> > mwsize m_in_q, n_in_q, points, layers
>
> mwsize might be 32-bit or 64-bit depending on compiling flags.
>
> (snip)
>
> > call comp(%val(pr_out),%val(pr_in),%val(pr_in2),%val(pr_in3),
> > + %val(pr_in4),%val(pr_in5),%val(pr_in6),
> > + %val(pr_in7),%val(pr_in8),layers,points)
>
> You then pass layers and points to comp above.
>
> (snip)
>
> > subroutine comp(out,x,sld,nbair,nbsub,ssub,nrepeats,resType,
> > + resol,layers,points)
> > integer size, i
> > integer layers,points,j,reploop, nl, loop, nrepeats
>
> Then in comp layers and points are delcared as integer, which again could be 32-bit or 64-bit depending on compiler and compiling flags.
>
> It is possible that mwsize will not match integer (one 32-bit and one 64-bit), in which case things might bomb.
>
> It is best to keep the declarations exactly the same in both routines. Either both default integer or both mwsize.
>
> James Tursa

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us