Matlab crashing when evaluating mex
조회 수: 6 (최근 30일)
이전 댓글 표시
I have the following C code, that I compile into a mex (32bit) with Visual Studio Express 2013:
#include <stdlib.h>
#include <stdio.h>
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
const size_t m = mxGetM(prhs[0]);
const size_t n = mxGetN(prhs[0]);
double** x = (double**)mxCalloc(n, m);
for (size_t i = 0; i < n; i++)
x[i] = (double*)mxCalloc(m, sizeof(double));
for (size_t i = 0; i < n; i++)
mxFree(x[i]);
mxFree(x);
}
It is basically just allocating space to store a 2D matrix passed from Matlab, then deallocating it (without setting any value). When I compile it into mexw32 with Visual Studio Express 2013, then execute the following in Matlab 2013b 32bit, it crashes Matlab:
n = 51; x = zeros(3,n); myMex(x)
Here's the top of the stack log from the crash:
Stack: [0x00430000,0x00c30000], sp=0x00c23f7c, free space=8143k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [ntdll.dll+0x2e43e] RtlInitUnicodeString+0x196
C [ntdll.dll+0x2e0a3] RtlFreeHeap+0x7e
C [kernel32.dll+0x114bd] HeapFree+0x14
C [MSVCR100.dll+0x1016a] free+0x1c
Does anyone have any idea whatI'm doing wrong here? Is it down to the way I deallocate each pointer?
Thanks in advance for your answers.
댓글 수: 0
채택된 답변
James Tursa
2016년 11월 3일
Here is some sample code for you to peruse. It takes a 2D matrix input and writes the input values to the screen using various methods. I prefer the first direct method, but the macro version of this has some readability advantages. I am not a big fan of using the [ ][ ] syntax in either methods shown. Whenever I encounter this style of coding for matrix access it always seems too burdensome to me and the perceived benefit simply to maintain the [ ][ ] coding style is not worth the trouble IMO. But to each his/her own, and I include them anyway.
/* Sample mex routine to demonstrate various ways to access an input 2D
* matrix at the C level.
*
* Programmer: James Tursa
*/
/* Includes ----------------------------------------------------------- */
#include "mex.h"
/* Macros ------------------------------------------------------------- */
#define VALUES(i,j) values[(i)+(j)*m]
/* Gateway ------------------------------------------------------------ */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
size_t nChannels, nSteps, i, j, m, n, mn;
double *values, *values_copy, *pr;
double **values_matrix;
/* Argument checks */
if( nlhs ) {
mexErrMsgTxt("Too many outputs.");
}
if( nrhs != 1 || !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) ||
mxIsSparse(prhs[0]) || mxGetNumberOfDimensions(prhs[0]) != 2 ) {
mexErrMsgTxt("Input must be a real full double 2D matrix.");
}
/* Get some input argument info */
m = nChannels = mxGetM(prhs[0]); /* Note that this is used in the macro VALUES */
n = nSteps = mxGetN(prhs[0]);
mn = m * n;
values = mxGetPr(prhs[0]);
/* Here is a way to access the data directly */
mexPrintf("\nDirect access using [ ] syntax:\n");
for( j=0; j<nSteps; j++ ) {
for( i=0; i<nChannels; i++ ) {
mexPrintf("matrix(%d,%d) = %g\n",i+1,j+1,values[i+j*m]);
}
}
/* Here is a way to access the data directly using a macro */
mexPrintf("\nDirect access using a macro:\n");
for( j=0; j<nSteps; j++ ) {
for( i=0; i<nChannels; i++ ) {
mexPrintf("matrix(%d,%d) = %g\n",i+1,j+1,VALUES(i,j));
}
}
/* Here is a way to access the data directly using [ ][ ] syntax */
mexPrintf("\nDirect access using [ ][ ] syntax:\n");
values_matrix = (double **) mxMalloc( nSteps * sizeof(*values_matrix) );
values_matrix[0] = values; /* 1st column pointer */
for( j=1; j<nSteps; j++ ) {
values_matrix[j] = values_matrix[j-1] + m; /* other column pointers */
}
for( j=0; j<nSteps; j++ ) {
for( i=0; i<nChannels; i++ ) {
mexPrintf("matrix(%d,%d) = %g\n",i+1,j+1,values_matrix[j][i]); /* Note [j][i] order */
}
}
mxFree(values_matrix);
/* Here is a way to copy the data to row-ordered memory to use [ ][ ] syntax on the copy */
/* Note that using this method, the copied data is guaranteed to be contiguous in memory */
/* This is not worth it IMO since you basically have to transpose the data in order to */
/* access it in the natural [ ][ ] C row-ordered syntax style ... quite inefficent use */
/* of resources simply to get this coding style benefit. */
mexPrintf("\nCopy access using [ ][ ] syntax:\n");
values_copy = (double *) mxMalloc( mn * sizeof(*values_copy) ); /* one contiguous block */
values_matrix = (double **) mxMalloc( nChannels * sizeof(*values_matrix) );
values_matrix[0] = values_copy; /* 1st row pointer */
for( i=1; i<nChannels; i++ ) {
values_matrix[i] = values_matrix[i-1] + n; /* other row pointers */
}
pr = values;
for( j=0; j<nSteps; j++ ) {
for( i=0; i<nChannels; i++ ) {
values_matrix[i][j] = *pr++; /* copy the column data into rows */
}
}
for( j=0; j<nSteps; j++ ) {
for( i=0; i<nChannels; i++ ) {
mexPrintf("matrix(%d,%d) = %g\n",i+1,j+1,values_matrix[i][j]); /* Note [i][j] order */
}
}
mxFree(values_matrix);
mxFree(values_copy);
}
And a sample run using this routine:
>> x = reshape(1:6,2,3)
x =
1 3 5
2 4 6
>> matrix_access(x)
Direct access using [ ] syntax:
matrix(1,1) = 1
matrix(2,1) = 2
matrix(1,2) = 3
matrix(2,2) = 4
matrix(1,3) = 5
matrix(2,3) = 6
Direct access using a macro:
matrix(1,1) = 1
matrix(2,1) = 2
matrix(1,2) = 3
matrix(2,2) = 4
matrix(1,3) = 5
matrix(2,3) = 6
Direct access using [ ][ ] syntax:
matrix(1,1) = 1
matrix(2,1) = 2
matrix(1,2) = 3
matrix(2,2) = 4
matrix(1,3) = 5
matrix(2,3) = 6
Copy access using [ ][ ] syntax:
matrix(1,1) = 1
matrix(2,1) = 2
matrix(1,2) = 3
matrix(2,2) = 4
matrix(1,3) = 5
matrix(2,3) = 6
추가 답변 (1개)
Jan
2016년 10월 27일
편집: Jan
2016년 11월 3일
const size_t m = mxGetM(prhs[0]);
const size_t n = mxGetN(prhs[0]);
Now m and n are 1, because the first input is a scalar.
In
double** x = (double**)mxCalloc(n, m);
you allocate memory for n elements of size m bytes, which is 1 byte.
x[i] = (double*)mxCalloc(...)
writes a pointer to a double, which has 32 or 64 bits depending on the system, to an element you reserved 1 byte for. This should crash Matlab.
Try this:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
const size_t m = (size_t) mxGetData(prhs[0]);
const size_t n = (size_t) mxGetData(prhs[1]);
double** x = (double**)mxCalloc(n, sizeof(double *));
for (size_t i = 0; i < n; i++)
x[i] = (double*) mxCalloc(m, sizeof(double));
for (size_t i = 0; i < n; i++)
mxFree(x[i]);
mxFree(x);
}
댓글 수: 4
James Tursa
2016년 10월 28일
편집: James Tursa
2016년 10월 28일
I think Jan had a typo. Go back to this:
const size_t m = mxGetM(prhs[0]);
const size_t n = mxGetN(prhs[0]);
That being said, this is still somewhat messy code IMO. What is the ultimate goal here? Will you be copying data back & forth between mxArray variables and your dynamically allocated memory? Are you just trying to learn how to use the double bracket [ ][ ] syntax with allocated memory? Or what? There may be better ways of going about things depending on what the end goal is. (e.g., with your method the data for this 2D matrix is not guaranteed to be contiguous in memory, but there are other methods of allocation that will guarantee this)
참고 항목
카테고리
Help Center 및 File Exchange에서 Matrix Indexing에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!