Using RAM by mex-function
Show older comments
Something strange occurs when I try to transfer matrices to mex-function. When matrices size is not big the mex-function perform well, but if size of my matrices about 500*500 and more matlab will crush without any message. The terminal reports about a segmentation fault.
#include "mex.h"
#include <iostream>
#include "CFullVec.h"
double GAMMA, Mnuclon;
int NR, NZ;
void mexFunction(int nlhs, mxArray *plhs[], // output to ML
int nrhs, const mxArray *prhs[]) // input to C++
{{
double *parGas, *parGrid, *parTime;
size_t mrows, ncols;
std::cout << "zdfgbDSFB" << std::endl;
// check nb of gas parameters
mrows = mxGetM(prhs[0]);
ncols = mxGetN(prhs[0]);
if(mrows!=2 || ncols!=1){
mexErrMsgIdAndTxt("MATLAB:mexcpp:nargin", "Incorrect vector of the gas parameters");
}
// check nb of grid parameters
mrows = mxGetM(prhs[1]);
ncols = mxGetN(prhs[1]);
if(mrows!=6 || ncols!=1){
mexErrMsgIdAndTxt("MATLAB:mexcpp:nargin", "Incorrect vector of the grid parameters");
}
// check nb of time parameters
mrows = mxGetM(prhs[2]);
ncols = mxGetN(prhs[2]);
if(mrows!=3 || ncols!=1){
mexErrMsgIdAndTxt("MATLAB:mexcpp:nargin", "Incorrect vector of the time parameters");
}
parGas=mxGetPr(prhs[0]);
double GAMMA = parGas[0];
double Mnuclon = parGas[1];
parGrid=mxGetPr(prhs[1]);
NR = static_cast<int>( (parGrid[1]-parGrid[0])/parGrid[2] ) + 1;
NZ = static_cast<int>( (parGrid[4]-parGrid[3])/parGrid[5] ) + 1;
parTime=mxGetPr(prhs[2]);
const int ST = static_cast<int>( parTime[0]/parTime[1] );
const int CVAR = static_cast<int>( parTime[0]/parTime[2] );
// check data dimensions
for(int i=3; i<=3+7; i++){
mrows = mxGetM(prhs[i]);
ncols = mxGetN(prhs[i]);
//std::cout << i << ' ' << mrows << ' ' << ncols << std::endl;
if(mrows!=NR+2 || ncols!=NZ+2){
// mexErrMsgIdAndTxt("MATLAB:mexcpp:nargin", "Incorrect array of initial data");
}
}
double *rho, *Vr, *Vp, *Vz, *Br, *Bp, *Bz, *T; // these pointers are used both to input and to output
// assign pointers to input
rho=mxGetPr(prhs[3]); Vr=mxGetPr(prhs[4]); Vp=mxGetPr(prhs[5]); Vz=mxGetPr(prhs[6]);
Br=mxGetPr(prhs[7]); Bp=mxGetPr(prhs[8]); Bz=mxGetPr(prhs[9]); T=mxGetPr(prhs[10]);
FullVec U[NR+2][NZ+2];
// something else....
The error happens in the last three lines. Also if the declaration of U[NR+2][NZ+2] is deleted the error may not happen. Therefore I think this error is associated with RAM, but the matrices take not more than 40-50 MB RAM and U[NR+2][NZ+2] takes about the same.
I use linux mint 64-bit. I add -largeArrayDims during compilation. Could you tell me, what is going wrong?
Accepted Answer
More Answers (1)
Ilya Kalash
on 5 Mar 2017
Edited: Ilya Kalash
on 6 Mar 2017
2 Comments
James Tursa
on 6 Mar 2017
Edited: James Tursa
on 6 Mar 2017
You almost got this correct, but not quite. Let me pick apart these lines of code to show you the crashing problem you have:
(1) double *rho = (double*)mxCalloc( (mwSize)nbAll,sizeof(double));
(2) rho = mxGetPr(prhs[3]);
:
(3) mxFree(rho);
Line (1) allocates memory from the heap via mxCalloc and assigns that memory address to rho. This is not what you really needed to do, but in and of itself causes no immediate harm.
Line (2) then turns around and wipes out the value you just stored in rho via (1) with another different memory address from mxGetPr. So you obliterated the heap address from (1) by overwriting it with another different address from (2). This creates a memory leak since that mxCalloc memory address is now lost to you as you have no handle to it saved in any variable. In particular, you will not be able to manually mxFree it because you have lost its value. (It turns out that MATLAB's garbage collection will cover you in this case and free the memory when the mex routine returns control to the caller, but it is not good programming practice to rely on this).
Line (3) frees the data pointer (the one you got via mxGetPr) that is currently attached to an existing mxArray. This is very bad since that mxArray is now in an invalid state. Any action that uses this mxArray and tries to access its data will be using an invalid pointer and likely result in a MATLAB crash. Even simply clearing this mxArray can crash MATLAB since the equivalent of mxFree will be called with an invalid pointer as input.
So, to fix this you need to get rid of lines (1) and (3). If you are trying to access the data area of an existing mxArray via mxGetPr (and friends), do not allocate any memory for this pointer ahead of time, and do not attempt to free it later. The data memory will automatically be freed whenever its associated mxArray gets destroyed, so you don't need to worry about that part.
Finally, I will point out that your current method of allocating the U[i] stuff will not guarantee that the actual data for all of these rows will be contiguous. I.e., one row will not necessarily be immediately adjacent to the next row in memory because they were allocated using separate mxCalloc calls. This may not be important to you in your downstream code, but I thought I would point it out to you. If you want the data to be contiguous in memory, use the technique I show in the link I provided above.
Ilya Kalash
on 9 Mar 2017
Categories
Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!