From: Clint on
Hello,

So I am new to the whole mex file and I'm using a fortran file which has been
working great through mex until I added the mxCreateNumericArray Command.
After adding this command if I try to cal the function cmsl4Integrated
(tempVec,zbndryVec) from matlab it crashes with "Out of memory. Type HELP
MEMORY for your options.

I really doubt this is the case since I even tried mxCreateNumericArray with
just a 2D array and it still gives the same error.. Without the
mxCreateNumericArray line the code runs fine from Matlab.

Below is my fortran file which i compile from matlab with mex cmsl4Interated.
f and this works fine.
Below that is the matlab command snipit that I use to call the function if
that is relevent.

#include "fintrf.h"
C======================================================================
#if 0
C
C cmsl4.F
C .F file needs to be preprocessed to generate .for equivalent
C
#endif
C
C cmsl4.f
C
C Computational function that takes temperature and displacement
C and returns optical field inside HEL resonator.

C This is a MEX-file for MATLAB.
C Copyright 1984-2009 The MathWorks, Inc.
C $Revision: 1.12.2.8 $
C======================================================================
C Gateway routine
subroutine mexFunction(nlhs, plhs, nrhs, prhs)

C Declarations
implicit none

C mexFunction arguments:
mwPointer plhs(*), prhs(*)
integer nlhs, nrhs

C Function declarations:
mwPointer mxGetPr,mxGetPi
mwPointer mxCreateDoubleMatrix,mxCreateNumericArray
integer*4 mxClassIDFromClassName
integer mxIsNumeric
mwSize mxGetM, mxGetN

C Pointers to input/output mxArrays:
mwPointer x_ptr1,x_ptr2,x_ptr3,y_ptr1,y_ptr2,y_ptri1,y_ptri2

C Array information:
mwSize mrows1,mrows2,ncols1,ncols2,size1,size2,fieldSize

C Arguments for mxCreateNumericArray
integer*4 classid
integer*4 complexflag
mwSize ndim
mwSize dims(1)

C Arguments for computational routine:
real*8 temp,zbndry,q
dimension temp(256,256,10,20),zbndry(256,256,2,20)
dimension q(256,256,10,20,2)
complex*16 c(1024,1024)

C-----------------------------------------------------------------------
C Check for proper number of arguments.
if(nrhs .ne. 2) then
call mexErrMsgIdAndTxt ('MATLAB:cmsl4:nInput',
+ 'Two inputs required.')
elseif(nlhs .gt. 2) then
call mexErrMsgIdAndTxt ('MATLAB:cmsl4:nOutput',
+ 'Too many output arguments.')
endif

C Validate inputs
C Check that the 1st input is numeric array.
if(mxIsNumeric(prhs(1)) .eq. 0.) then
call mexErrMsgIdAndTxt ('MATLAB:cmsl4:NonNumeric',
+ 'Input1 must be numeric.')
endif

C Check that the 2nd input is numeric array.
if(mxIsNumeric(prhs(2)) .eq. 0.) then
call mexErrMsgIdAndTxt ('MATLAB:cmsl4:NonNumeric',
+ 'Input2 must be numeric.')
endif



C Get the size of the first input array.
mrows1 = mxGetM(prhs(1))
ncols1 = mxGetN(prhs(1))
size1 = mrows1*ncols1

C Get the size of the 2nd input array.
mrows2 = mxGetM(prhs(2))
ncols2 = mxGetN(prhs(2))
size2 = mrows2*ncols2


C Create Fortran array from the 1st input argument.
x_ptr1 = mxGetPr(prhs(1))
call mxCopyPtrToReal8(x_ptr1,temp,size1)

C Create Fortran array from the 2nd input argument.
x_ptr2 = mxGetPr(prhs(2))
call mxCopyPtrToReal8(x_ptr2,zbndry,size2)

C Create matrix for the return argument.
plhs(1) = mxCreateDoubleMatrix(1024,1024,1)
fieldSize = 1024*1024
y_ptr1 = mxGetPr(plhs(1))
y_ptri1 = mxGetPi(plhs(1))

C Create matrix for the return argument q.
classid = mxClassIDFromClassName('REAL*8')
complexflag = 0
ndim = 2
dims(1) = 256
dims(2) = 256
dims(3) = 10
dims(4) = 20
dims(5) = 2
plhs(2) = mxCreateNumericArray(ndim,dims,classid,complexflag)
y_ptr2 = mxGetPr(plhs(2))

C Call the computational subroutine.
call cmsl4(q,c,temp,zbndry)
C Load the data into y_ptr, which is the output to MATLAB.
call mxCopyComplex16ToPtr(c,y_ptr1,y_ptri1,fieldSize)
call mxCopyReal8ToPtr(q,y_ptr2,mxGetM(plhs(2))*mxGetN(plhs(2)))
call mxDestroyArray(plhs(2))
call mxDestroyArray(plhs(1))

return
end

C-----------------------------------------------------------------------
C Computational routine

Inside Matlab file.....................................................

tempVec = ones(256,256,10,20).*573;
zbndryVec = ones(256,256,2,20).*0.75E-3;
zbndryVec(:,:,1,:)= -zbndryVec(:,:,1,:);

[field,q] = cmsl4Integrated(tempVec,zbndryVec);

........................................................................

Any help would be appreciated:
From: James Tursa on
"Clint " <clint.zeringue(a)kirtland.af.mil> wrote in message <i3c74t$9r2$1(a)fred.mathworks.com>...
> Hello,
>
> So I am new to the whole mex file and I'm using a fortran file which has been
> working great through mex until I added the mxCreateNumericArray Command.
> After adding this command if I try to cal the function cmsl4Integrated
> (tempVec,zbndryVec) from matlab it crashes with "Out of memory. Type HELP
> MEMORY for your options.
>
> I really doubt this is the case since I even tried mxCreateNumericArray with
> just a 2D array and it still gives the same error.. Without the
> mxCreateNumericArray line the code runs fine from Matlab.
>
> Below is my fortran file which i compile from matlab with mex cmsl4Interated.
> f and this works fine.
> Below that is the matlab command snipit that I use to call the function if
> that is relevent.
>
> #include "fintrf.h"
> C======================================================================
> #if 0
> C
> C cmsl4.F
> C .F file needs to be preprocessed to generate .for equivalent
> C
> #endif
> C
> C cmsl4.f
> C
> C Computational function that takes temperature and displacement
> C and returns optical field inside HEL resonator.
>
> C This is a MEX-file for MATLAB.
> C Copyright 1984-2009 The MathWorks, Inc.
> C $Revision: 1.12.2.8 $
> C======================================================================
> C Gateway routine
> subroutine mexFunction(nlhs, plhs, nrhs, prhs)
>
> C Declarations
> implicit none
>
> C mexFunction arguments:
> mwPointer plhs(*), prhs(*)
> integer nlhs, nrhs
>
> C Function declarations:
> mwPointer mxGetPr,mxGetPi
> mwPointer mxCreateDoubleMatrix,mxCreateNumericArray
> integer*4 mxClassIDFromClassName
> integer mxIsNumeric
> mwSize mxGetM, mxGetN
>
> C Pointers to input/output mxArrays:
> mwPointer x_ptr1,x_ptr2,x_ptr3,y_ptr1,y_ptr2,y_ptri1,y_ptri2
>
> C Array information:
> mwSize mrows1,mrows2,ncols1,ncols2,size1,size2,fieldSize
>
> C Arguments for mxCreateNumericArray
> integer*4 classid
> integer*4 complexflag
> mwSize ndim
> mwSize dims(1)

You have a serious, crash inducing, error in dims. Here you only allocate space for 1 element yet below you fill in 5 elements.

>
> C Arguments for computational routine:
> real*8 temp,zbndry,q
> dimension temp(256,256,10,20),zbndry(256,256,2,20)
> dimension q(256,256,10,20,2)
> complex*16 c(1024,1024)
>
> C-----------------------------------------------------------------------
> C Check for proper number of arguments.
> if(nrhs .ne. 2) then
> call mexErrMsgIdAndTxt ('MATLAB:cmsl4:nInput',
> + 'Two inputs required.')
> elseif(nlhs .gt. 2) then
> call mexErrMsgIdAndTxt ('MATLAB:cmsl4:nOutput',
> + 'Too many output arguments.')
> endif
>
> C Validate inputs
> C Check that the 1st input is numeric array.
> if(mxIsNumeric(prhs(1)) .eq. 0.) then
> call mexErrMsgIdAndTxt ('MATLAB:cmsl4:NonNumeric',
> + 'Input1 must be numeric.')
> endif
>
> C Check that the 2nd input is numeric array.
> if(mxIsNumeric(prhs(2)) .eq. 0.) then
> call mexErrMsgIdAndTxt ('MATLAB:cmsl4:NonNumeric',
> + 'Input2 must be numeric.')
> endif
>
>
>
> C Get the size of the first input array.
> mrows1 = mxGetM(prhs(1))
> ncols1 = mxGetN(prhs(1))
> size1 = mrows1*ncols1
>
> C Get the size of the 2nd input array.
> mrows2 = mxGetM(prhs(2))
> ncols2 = mxGetN(prhs(2))
> size2 = mrows2*ncols2
>
>
> C Create Fortran array from the 1st input argument.
> x_ptr1 = mxGetPr(prhs(1))
> call mxCopyPtrToReal8(x_ptr1,temp,size1)
>
> C Create Fortran array from the 2nd input argument.
> x_ptr2 = mxGetPr(prhs(2))
> call mxCopyPtrToReal8(x_ptr2,zbndry,size2)
>
> C Create matrix for the return argument.
> plhs(1) = mxCreateDoubleMatrix(1024,1024,1)
> fieldSize = 1024*1024
> y_ptr1 = mxGetPr(plhs(1))
> y_ptri1 = mxGetPi(plhs(1))
>
> C Create matrix for the return argument q.
> classid = mxClassIDFromClassName('REAL*8')

There is no 'REAL*8' MATLAB class name. This should be:

classid = mxClassIDFromClassName('double')

> complexflag = 0
> ndim = 2
> dims(1) = 256
> dims(2) = 256
> dims(3) = 10
> dims(4) = 20
> dims(5) = 2
> plhs(2) = mxCreateNumericArray(ndim,dims,classid,complexflag)

Here you fill in 5 elements for dims even though it only has 1 element. You are writing beyond the valid array bounds, corrupting memory, and inducing a crash. You need to allocate 5 elements for dims in the declaration above if you wish to fill in 5 elements here.

Also, your ndim = 2 doesn't make any sense. If you want to use 5 elements of dims then you should set ndim = 5.


> y_ptr2 = mxGetPr(plhs(2))
>
> C Call the computational subroutine.
> call cmsl4(q,c,temp,zbndry)
> C Load the data into y_ptr, which is the output to MATLAB.
> call mxCopyComplex16ToPtr(c,y_ptr1,y_ptri1,fieldSize)
> call mxCopyReal8ToPtr(q,y_ptr2,mxGetM(plhs(2))*mxGetN(plhs(2)))

Another crash. Here you are using plhs(2) but you haven't created it. So plhs(2) at this point is garbage and you are dereferencing garbage pointers every time you pass plhs(2) to a function.

> call mxDestroyArray(plhs(2))
> call mxDestroyArray(plhs(1))

I don't understand. The plhs array is for variables that you are returning to the MATLAB workspace. Why are you destroying them? Also, if you create a plhs(1) as in your above code that sets it to a non-NULL value. Then if you subsequently destroy it but don't tell MATLAB about it then MATLAB will try to use it and access invalid memory and crash. If you really, really want to destroy the plhs variables (which I doubt) then you should do this:

call mxDestroyArray(plhs(2))
plhs(2) = 0
call mxDestroyArray(plhs(1))
plhs(1) = 0

That way when the mex file returns MATLAB knows that there is nothing in those arrays.

James Tursa
From: Clint on
"James Tursa" <aclassyguy_with_a_k_not_a_c(a)hotmail.com> wrote in message <i3cdfd$bkr$1(a)fred.mathworks.com>...
> "Clint " <clint.zeringue(a)kirtland.af.mil> wrote in message <i3c74t$9r2$1(a)fred.mathworks.com>...
> > Hello,
> >
> > So I am new to the whole mex file and I'm using a fortran file which has been
> > working great through mex until I added the mxCreateNumericArray Command.
> > After adding this command if I try to cal the function cmsl4Integrated
> > (tempVec,zbndryVec) from matlab it crashes with "Out of memory. Type HELP
> > MEMORY for your options.
> >
> > I really doubt this is the case since I even tried mxCreateNumericArray with
> > just a 2D array and it still gives the same error.. Without the
> > mxCreateNumericArray line the code runs fine from Matlab.
> >
> > Below is my fortran file which i compile from matlab with mex cmsl4Interated.
> > f and this works fine.
> > Below that is the matlab command snipit that I use to call the function if
> > that is relevent.
> >
> > #include "fintrf.h"
> > C======================================================================
> > #if 0
> > C
> > C cmsl4.F
> > C .F file needs to be preprocessed to generate .for equivalent
> > C
> > #endif
> > C
> > C cmsl4.f
> > C
> > C Computational function that takes temperature and displacement
> > C and returns optical field inside HEL resonator.
> >
> > C This is a MEX-file for MATLAB.
> > C Copyright 1984-2009 The MathWorks, Inc.
> > C $Revision: 1.12.2.8 $
> > C======================================================================
> > C Gateway routine
> > subroutine mexFunction(nlhs, plhs, nrhs, prhs)
> >
> > C Declarations
> > implicit none
> >
> > C mexFunction arguments:
> > mwPointer plhs(*), prhs(*)
> > integer nlhs, nrhs
> >
> > C Function declarations:
> > mwPointer mxGetPr,mxGetPi
> > mwPointer mxCreateDoubleMatrix,mxCreateNumericArray
> > integer*4 mxClassIDFromClassName
> > integer mxIsNumeric
> > mwSize mxGetM, mxGetN
> >
> > C Pointers to input/output mxArrays:
> > mwPointer x_ptr1,x_ptr2,x_ptr3,y_ptr1,y_ptr2,y_ptri1,y_ptri2
> >
> > C Array information:
> > mwSize mrows1,mrows2,ncols1,ncols2,size1,size2,fieldSize
> >
> > C Arguments for mxCreateNumericArray
> > integer*4 classid
> > integer*4 complexflag
> > mwSize ndim
> > mwSize dims(1)
>
> You have a serious, crash inducing, error in dims. Here you only allocate space for 1 element yet below you fill in 5 elements.
>
> >
> > C Arguments for computational routine:
> > real*8 temp,zbndry,q
> > dimension temp(256,256,10,20),zbndry(256,256,2,20)
> > dimension q(256,256,10,20,2)
> > complex*16 c(1024,1024)
> >
> > C-----------------------------------------------------------------------
> > C Check for proper number of arguments.
> > if(nrhs .ne. 2) then
> > call mexErrMsgIdAndTxt ('MATLAB:cmsl4:nInput',
> > + 'Two inputs required.')
> > elseif(nlhs .gt. 2) then
> > call mexErrMsgIdAndTxt ('MATLAB:cmsl4:nOutput',
> > + 'Too many output arguments.')
> > endif
> >
> > C Validate inputs
> > C Check that the 1st input is numeric array.
> > if(mxIsNumeric(prhs(1)) .eq. 0.) then
> > call mexErrMsgIdAndTxt ('MATLAB:cmsl4:NonNumeric',
> > + 'Input1 must be numeric.')
> > endif
> >
> > C Check that the 2nd input is numeric array.
> > if(mxIsNumeric(prhs(2)) .eq. 0.) then
> > call mexErrMsgIdAndTxt ('MATLAB:cmsl4:NonNumeric',
> > + 'Input2 must be numeric.')
> > endif
> >
> >
> >
> > C Get the size of the first input array.
> > mrows1 = mxGetM(prhs(1))
> > ncols1 = mxGetN(prhs(1))
> > size1 = mrows1*ncols1
> >
> > C Get the size of the 2nd input array.
> > mrows2 = mxGetM(prhs(2))
> > ncols2 = mxGetN(prhs(2))
> > size2 = mrows2*ncols2
> >
> >
> > C Create Fortran array from the 1st input argument.
> > x_ptr1 = mxGetPr(prhs(1))
> > call mxCopyPtrToReal8(x_ptr1,temp,size1)
> >
> > C Create Fortran array from the 2nd input argument.
> > x_ptr2 = mxGetPr(prhs(2))
> > call mxCopyPtrToReal8(x_ptr2,zbndry,size2)
> >
> > C Create matrix for the return argument.
> > plhs(1) = mxCreateDoubleMatrix(1024,1024,1)
> > fieldSize = 1024*1024
> > y_ptr1 = mxGetPr(plhs(1))
> > y_ptri1 = mxGetPi(plhs(1))
> >
> > C Create matrix for the return argument q.
> > classid = mxClassIDFromClassName('REAL*8')
>
> There is no 'REAL*8' MATLAB class name. This should be:
>
> classid = mxClassIDFromClassName('double')
>
> > complexflag = 0
> > ndim = 2
> > dims(1) = 256
> > dims(2) = 256
> > dims(3) = 10
> > dims(4) = 20
> > dims(5) = 2
> > plhs(2) = mxCreateNumericArray(ndim,dims,classid,complexflag)
>
> Here you fill in 5 elements for dims even though it only has 1 element. You are writing beyond the valid array bounds, corrupting memory, and inducing a crash. You need to allocate 5 elements for dims in the declaration above if you wish to fill in 5 elements here.
>
> Also, your ndim = 2 doesn't make any sense. If you want to use 5 elements of dims then you should set ndim = 5.
>
>
> > y_ptr2 = mxGetPr(plhs(2))
> >
> > C Call the computational subroutine.
> > call cmsl4(q,c,temp,zbndry)
> > C Load the data into y_ptr, which is the output to MATLAB.
> > call mxCopyComplex16ToPtr(c,y_ptr1,y_ptri1,fieldSize)
> > call mxCopyReal8ToPtr(q,y_ptr2,mxGetM(plhs(2))*mxGetN(plhs(2)))
>
> Another crash. Here you are using plhs(2) but you haven't created it. So plhs(2) at this point is garbage and you are dereferencing garbage pointers every time you pass plhs(2) to a function.
>
> > call mxDestroyArray(plhs(2))
> > call mxDestroyArray(plhs(1))
>
> I don't understand. The plhs array is for variables that you are returning to the MATLAB workspace. Why are you destroying them? Also, if you create a plhs(1) as in your above code that sets it to a non-NULL value. Then if you subsequently destroy it but don't tell MATLAB about it then MATLAB will try to use it and access invalid memory and crash. If you really, really want to destroy the plhs variables (which I doubt) then you should do this:
>
> call mxDestroyArray(plhs(2))
> plhs(2) = 0
> call mxDestroyArray(plhs(1))
> plhs(1) = 0
>
> That way when the mex file returns MATLAB knows that there is nothing in those arrays.
>
> James Tursa

Hi James,

Thanks! All your suggestions worked like a charm. I was destroying them becuase I was under the impression that you were supposed to clean out the memory after I returend them to matlab. I suppose that is happening automatically?
From: James Tursa on
"James Tursa" <aclassyguy_with_a_k_not_a_c(a)hotmail.com> wrote in message <i3cdfd$bkr$1(a)fred.mathworks.com>...
>
> Here you are using plhs(2) but you haven't created it. ...

.... disregard this comment.

James Tursa
From: James Tursa on
"Clint " <clint.zeringue(a)kirtland.af.mil> wrote in message <i3ceqj$8ak$1(a)fred.mathworks.com>...
>
> Thanks! All your suggestions worked like a charm. I was destroying them becuase I was under the impression that you were supposed to clean out the memory after I returend them to matlab. I suppose that is happening automatically?

Yes and no. Anything that is part of a variable being returned to MATLAB via the plhs array should *not* be destroyed. Those will become part of the workspace in the routine that is calling your mex function and you definitely don't want to invalidate those variables before you return. Anything else you allocate for temporary purposes that is not being returned in the plhs array should be destroyed. MATLAB is nice to you, however, in that if you don't destroy these other temporary items then it will do so automatically when the mex function returns to MATLAB. But I consider this bad programming practice and poor memory management, so I would advise manually destroying them yourself when you are done with them.

James Tursa