Crash with a mex file, using mxMalloc, mxCalloc and complex vectors
조회 수: 2 (최근 30일)
이전 댓글 표시
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
댓글 수: 0
채택된 답변
James Tursa
2012년 10월 8일
편집: James Tursa
2012년 10월 8일
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.
추가 답변 (2개)
James Tursa
2012년 10월 8일
You use N before you set its value:
signal = mxMalloc(2*N*sizeof(mxCOMPLEX)); // Use it here
/* get dimensions of the input matrix */
N = mxGetM(prhs[0]); // Set its value here
Also, you should not be using sizeof(mxCOMPLEX) or sizeof(mxREAL) for memory allocation. mxCOMPLEX and mxREAL are enumeration integer values used as flags in API calls ... they are not the data type itself. In your memory allocation:
signal = mxMalloc(2*N*sizeof(*signal));
:
sigi = mxCalloc(N, sizeof(*sigi));
:
gft = mxCalloc(2*N,sizeof(*gft));
In addition, for the complex ones that you had you may need to use 2*N instead of N as noted.
댓글 수: 0
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!