MATLAB: Crash with a mex file, using mxMalloc, mxCalloc and complex vectors

complex vectorsmexmxcallocmxmalloc

Hi,
I am trying to write a mex file but I can't find out what does not work in it. I have "emptied" it and wrote a test one but it still doesn't work. Matlab is killed each time I try to run it. To run it, I take a random signal: x = randn(1,16); and then type y = test(x) Could you give me a hint? Here is the code:
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/utsname.h>
#endif
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int N, *partitions;
int taille, i;
double *partdouble;
double *sigi, *sigr, *gftr, *gfti, *win, *signal, *gft;
char *windowtype;
void *window;
/* create a pointer to the real data in the input matrix */
sigr = mxGetPr(prhs[0]);
signal = mxMalloc(2*N*sizeof(mxCOMPLEX));
/* get dimensions of the input matrix */
N = mxGetM(prhs[0]);
if (N == 1)
N = mxGetN(prhs[0]);
/* If not complex, set imaginary part to 0 */
if (!mxIsComplex(prhs[0]))
sigi = mxCalloc(N, sizeof(mxREAL));
else
sigi = mxGetPi(prhs[0]);
/* In C, real and complex values are interleaved whereas in Matlab
* there are split. Therefore create a complex signal of size 2N with 0
* interleaved as the original signal is real */
for (i = 0; i<N; i++) {
signal[i] = sigr[i];
signal[2*i+1] = sigi[i];
}
/* create the output matrix */
plhs[0] = mxCreateDoubleMatrix(1,N, mxCOMPLEX);
/* get a pointer to the real data in the output matrix */
gftr = mxGetPr(plhs[0]);
gfti = mxGetPi(plhs[0]);
gft = mxCalloc(N,sizeof(mxCOMPLEX));
for (i=0; i<2*N; i++){
gft[i] = signal[i];
}
for (i = 0; i<N; i++) {
mexPrintf("gft[%d] = %lf\t gft[%d] = %lf\n", 2*i, gft[2*i], 2*i+1, gft[2*i+1]);
gftr[i] = gft[2*i];
gfti[i] = gft[2*i+1];
}
mexPrintf("The end\n");
}
One of the side questions is that as signal should be an N-complex vector, should I declare it as signal = mxMalloc(2*N*sizeof(mxCOMPLEX)); or signal = mxMalloc(N*sizeof(mxCOMPLEX));? Cheers, Carine

Best Answer

This loop is wrong for the real part sigr:
for (i = 0; i<N; i++) {
signal[i] = sigr[i]; // should be signal[2*i] = etc.
signal[2*i+1] = sigi[i];
}
You ignored my previous advice about the size of gft. Since it is the interleaved complex data, it needs to be allocated to 2*N, not N (this is what is causing the seg fault):
gft = mxCalloc(N,sizeof(*gft)); // should be 2*N, not N
Also, as an efficiency suggestion, I would not allocate a 0 block for sigi up front. That is wasted effort and memory and slows down the code. I know this makes the downstream code simpler, but I would still opt for a bit of extra code downstream to handle it vice extra memory & copying. E.g., something like this:
if (mxIsComplex(prhs[0])) {
sigi = mxGetPi(prhs[0]);
for (i = 0; i<N; i++) {
signal[2*i ] = sigr[i];
signal[2*i+1] = sigi[i];
}
} else {
for (i = 0; i<N; i++) {
signal[2*i ] = sigr[i];
signal[2*i+1] = 0.0; // might not need this, see below
}
}
This also avoids the need to conditionally free sigi downstream (which you did not do btw). All of the mxCreateEtc API functions 0 out the data areas, which is why you don't need to explicitly do this in your code. Additionally, it appears that mxMalloc also 0's out the memory it returns from all tests I have done. If you don't want to rely on that then use mxCalloc or explicitly 0 out the imaginary elements in your code.
Related Question