运行MEX文件时MATLAB崩溃 [英] MATLAB crashes when I run MEX file
问题描述
我正在尝试编写一个mex文件,在评估mex时,每次运行MATLAB都会崩溃.这是我编写的C ++代码的一部分:
I am trying to write a mex file, When Evaluating the mex, MATLAB crashes up every time I ran it. Here is a part of C++ code that I wrote :
void mexFunction(mwSize nlhs, mxArray *plhs[],
mwSize nrhs, const mxArray *prhs[]){
vector<int> *NNLt;
double *NNLtout;
Vector *V;
Vector *Fb;
mwSize *sn;
mwSize nsn;
mwSize nf;
double hs;
double bw;
double mw;
mwSize ncols;
mwSize i;
double *NNLtoutt;
/* check for proper number of arguments */
if(nrhs!=9) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","Nine inputs required.");
}
if(nlhs!=1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs","One output required.");
}
/* get the value of the scalar input */
nsn = mxGetScalar(prhs[4]);
nf = mxGetScalar(prhs[5]);
hs = mxGetScalar(prhs[6]);
bw = mxGetScalar(prhs[7]);
mw = mxGetScalar(prhs[8]);
/* create a pointer to the real data in the input matrix */
NNLt = (vector<int> *)mxGetData(prhs[0]);
V = (Vector *)mxGetData(prhs[1]);
Fb =(Vector *)mxGetData(prhs[2]);
sn = (mwSize *)mxGetData(prhs[3]);
/* call the computational routine */
createNNLtriangle(NNLt, V, Fb, sn, nsn, nf, hs, bw, mw);
/* create the output matrix */
plhs[0] = mxCreateCellMatrix(nsn,50);
for(i=0;i<nsn;i++){
mxArray* tmp = mxCreateDoubleMatrix(1, NNLt[i].size(), mxREAL);
copy(NNLt[i].begin(), NNLt[i].end(), mxGetPr(tmp));
mxSetCell(plhs[0], i, tmp);
mxFree(tmp);
}}
所以,我收到以下错误消息:
So , I am getting following errors:
------------------------------------------------------------------------
Segmentation violation detected at Thu Aug 2 14:41:25 2018
------------------------------------------------------------------------
...
Stack Trace (from fault):
[ 0] 0x00007f0b0c635426 /home/user/dir/createNNLtriangle.mexa64+00005158
[ 1] 0x00007f0b0c635893 /home/user/dir/createNNLtriangle.mexa64+00006291 mexFunction+00000240
[ 2] 0x00007f0c562cac4a /home/user/bin/glnxa64/libmex.so+00142410 mexRunMexFile+00000090
...
对于我们造成的混乱,同事们的澄清和其他问题,我们深表歉意.
we are sorry for the mess we created, here the clarifications and additional questions of my colleague.
您可以找到我们如何定义"NNLt".而这里的"tmp"是什么意思?
You can find how we define "NNLt". And what means your "tmp" here?
std::copy(mxGetPr(tmp), mxGetPr(tmp)+N, NNLt.begin());
下面是Mexfile中的cpp函数,它在MexFunction之前:
Below is the cpp function in Mexfile which is before MexFunction:
#include "mex.h"
#include "matrix.h"
#include <omp.h>
#include "vema.h"s
#include "eig3.h"
#include <stdlib.h>
#include <iostream>
#include <cmath>
#include <vector>
#include <fstream>
#include <iomanip>
#include <sys/types.h>
#include <sys/stat.h>
using namespace std;
Vector closestPointTriangle(Vector&, Vector&, Vector&, Vector&, double&, double&, double&);
// Generates pomwSize-triangle proximity lists using the linked cell algorithm
void createNNLtriangle(vector<int>* NNLt, Vector* Ut, Vector* faces, int* SN, mwSize nsn, mwSize nf, double hs, double bw, double mw) {
int mx = max(1, (int)(bw/mw)); // ** = 40 cells bw=3.2, mw=0.08
vector<int> head(mx*mx*mx, -1);
vector<int> list(nf);
// std::vector<int> head(mx*mx*mx, -1); //****** mx*mx*mx cells nomber, size mx*mx*mx vector with all values are -1, 40*40*40 = 64000
// std::vector<int> list(nf); // **** nf = 101882
int xa, ya, za, xi, yi, zi;
double ub, vb, wb;
int pt, tri;
Vector cog;
for (int i = 0; i < nf; i++) { // Divide triangle faces mwSizeo cells, i index of face
//Vector cog = (Ut[faces[i].n1] + Ut[faces[i].n2] + Ut[faces[i].n3])/3.0;
cog = (Ut[(int)faces[i].x] + Ut[(int)faces[i].y] + Ut[(int)faces[i].z])/3.0;
int xa = (int)((cog.x + 0.5*bw)/bw*mx);
int ya = (int)((cog.y + 0.5*bw)/bw*mx);
int za = (int)((cog.z + 0.5*bw)/bw*mx);
int tmp = mx*mx*za + mx*ya + xa; // *** 1641838 > 64000
list[i]=head[mx*mx*za + mx*ya + xa];
head[mx*mx*za + mx*ya + xa] = i;
}
#pragma omp parallel for
for (int i = 0; i < nsn; i++) { // Search cells around each pomwSize and build proximity list
int pt = SN[i];
NNLt[i].clear();
int xa = (int)((Ut[pt].x + 0.5*bw)/bw*mx);
int ya = (int)((Ut[pt].y + 0.5*bw)/bw*mx);
int za = (int)((Ut[pt].z + 0.5*bw)/bw*mx);
for (int xi = max(0, xa-1); xi <= min(mx-1, xa+1); xi++)// *** Browse head list
for (int yi = max(0, ya-1); yi <= min(mx-1, ya+1); yi++)
for (int zi = max(0, za-1); zi <= min(mx-1, za+1); zi++) {
int tri = head[mx*mx*zi + mx*yi + xi];
while (tri != -1) {
if ( pt != (int)faces[tri].x && pt != (int)faces[tri].y && pt != (int)faces[tri].z ) {
if ( (closestPointTriangle(Ut[pt], Ut[(int)faces[tri].x], Ut[(int)faces[tri].y], Ut[(int)faces[tri].z], ub, vb, wb) - Ut[pt]).length() < hs) {
NNLt[i].push_back(tri);
}
}
tri = list[tri];
}
}
}
}
// Returns the closest pomwSize of triangle abc to pomwSize p ***** a or b or c, if not, pt projection through the barycenter inside the triangle
Vector closestPointTriangle(Vector& p, Vector& a, Vector& b, Vector& c, double& u, double& v, double& w) {
Vector ab = b - a;
Vector ac = c - a;
Vector ap = p - a;
double d1 = ab.dot(ap);
double d2 = ac.dot(ap);
if (d1 <= 0.0 && d2 <= 0.0) {
u = 1.0;
v = 0.0;
w = 0.0;
return a;
}
Vector bp = p - b;
double d3 = ab.dot(bp);
double d4 = ac.dot(bp);
if (d3 >= 0.0 && d4 <= d3) {
u = 0.0;
v = 1.0;
w = 0.0;
return b;
}
double vc = d1*d4 - d3*d2;
if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) {
v = d1 / (d1 - d3);
u = 1.0 - v;
w = 0.0;
return a + ab * v;
}
Vector cp = p - c;
double d5 = ab.dot(cp);
double d6 = ac.dot(cp);
if (d6 >= 0.0 && d5 <= d6) {
u = 0.0;
v = 0.0;
w = 1.0;
return c;
}
double vb = d5*d2 - d1*d6;
if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) {
w = d2 / (d2 - d6);
u = 1.0 - w;
v = 0.0;
return a + ac * w;
}
double va = d3*d6 - d5*d4;
if (va <= 0.0 && (d4 - d3) >= 0.0 && (d5 - d6) >= 0.0) {
w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
u = 0.0;
v = 1.0 - w;
return b + (c - b) * w;
}
double denom = 1.0 / (va + vb + vc);
v = vb * denom;
w = vc * denom;
u = 1.0 - v - w;
return a + ab * v + ac * w;
}
下面是在Matlab中调用Mexfile的部分:
Below is the part to call Mexfile in Matlab:
NNLt = cell(1,nsn);
V = A(1:n,1:3); //A: Matrix
Fb = A(n:2*n,1:3);
nf = size(Fb,1);
sn = B(1,:); //B: Matrix
parfor i = 1:nsn
maxDist = max(maxDist, length(V(sn(i),:) - Vtold(i,:)));
end
if maxDist > 0.5*(hs-hc)
[NNLt] = createNNLtriangle(NNLt, V, Fb, sn, nsn, nf, hs, bw, mw);
for i = 1:nsn
Vtold(i,:) = V(sn(i),:);
end
end
最后,这是我们的V和Fb定义的"Vector *"类:
and finally, This is our "Vector*" Class for the definition of our V and Fb:
class Vector{
public:
double x, y, z;
Vector(): x(0.0), y(0.0), z(0.0) {};
Vector(double ax, double ay, double az): x(ax), y(ay), z(az) {};
double length(){
return sqrt(x*x + y*y + z*z);
}
double dot(const Vector& b){
return x*b.x + y*b.y + z*b.z;
}
Vector cross(const Vector& b){
return Vector(y*b.z - z*b.y, z*b.x - x*b.z, x*b.y - y*b.x);
}
void normalize(){
double temp = 1.0/length();
x *= temp;
y *= temp;
z *= temp;
}
void clear(){
x = y = z = 0.0;
}
Vector& operator+= (const Vector& b){
x += b.x;
y += b.y;
z += b.z;
return *this;
}
Vector& operator-= (const Vector& b){
x -= b.x;
y -= b.y;
z -= b.z;
return *this;
}
Vector& operator*= (const double& c){
x *= c;
y *= c;
z *= c;
return *this;
}
Vector& operator/= (const double& c){
x /= c;
y /= c;
z /= c;
return *this;
}
Vector operator+ (const Vector& b){
Vector r = *this;
return r += b;
}
Vector operator- (const Vector& b){
Vector r = *this;
return r -= b;
}
Vector operator* (const double& c){
Vector r = *this;
return r *= c;
}
Vector operator/ (const double& c){
Vector r = *this;
return r /= c;
}
};
再次
很抱歉! 谢谢, 干杯
again, we are sorry ! Thanks, Cheers
推荐答案
As rahnema1 said in a comment, you cannot cast the output of mxGetData
to whatever pointer type you need. This output points to the data of a mxArray
, and you need to read it as such.
例如,
NNLt = (vector<int> *)mxGetData(prhs[0]);
A vector<int>
是特定的C ++数据结构,您正在将MATLAB数组中的数据重新解释为C ++数据结构.该数据结构的元素之一是指向数据的指针,因此您正在将(大概)双浮点值重新解释为指针,然后访问该指针,显然会导致崩溃.
A vector<int>
is a specific C++ data structure, you are reinterpreting the data in a MATLAB array as the C++ data structure. One of this data strcuture's elements is a pointer to data, so you are reinterpreting a (presumably) double floating-point value as a pointer, then accessing that pointer, which obviously causes a crash.
您对Vector*
的强制转换也是如此,尽管我不知道此类是什么.
The same is true for your casts to Vector*
, though I don't know what this class is.
相反,首先请确保输入的类型正确,然后将数据复制到以下位置:
Instead, first make sure your input is of the correct type, then copy the data over:
if(!mxIsDouble(prhs[0])) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","First input must be a double array.");
}
std::size_t N = mxGetNumberOfElements(prhs[0]);
std::vector<int> NNLt(N);
std::copy(mxGetPr(prhs[0]), mxGetPr(prhs[0])+N, NNLt.begin());
但是,从代码其余部分来看,似乎NNLt
应该是向量的向量,而不是单个向量. createNNLtriangle
函数是否来自此处?这看起来像是对C和C ++的可怕破坏……
However, from the rest of your code, it seems like NNLt
is supposed to be a vector of vectors, not a single vector. Is the createNNLtriangle
function taken from here? That looks like a horrible mangling of C and C++...
也许您然后需要在此处执行以下操作:
Maybe you then need to do something like this here:
if(!mxIsDouble(prhs[0])) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","First input must be a double array.");
}
std::size_t M = mxGetM(prhs[0]); // number of rows
std::size_t N = mxGetN(prhs[0]); // number of columns
std::vector<std::vector<int>> NNLt(N, std::vector<int>(M));
double* ptr = mxGetPr(prhs[0]);
for(std::size_t ii = 0; ii < N; ++ii) {
std::copy(ptr, ptr+M, NNLt[ii].begin());
ptr += M;
}
// mwSize nsn = static_cast<mwSize>(mxGetScalar(prhs[4])); // Ignore this value!
// ... read the other values here in the same way
createNNLtriangle(NNLt.data(), V, Fb, sn, N, nf, hs, bw, mw);
// ^^^^^^^^^^^ ^--- NOTE!
还请注意,第三个参数Fb
是vector<Face>
,而不是Vector*
.您将必须弄清楚如何转换Vector*
和vector<Face>
,它将涉及到很多上述代码,而不仅仅是转换指针!
Note also that the third argument, Fb
, is a vector<Face>
, not a Vector*
. You'll have to figure out how to convert Vector*
and vector<Face>
, it'll involve quite a bit of code as above, not just casting the pointer!
第四个参数是int*
,而不是mwSize*
:
And the 4th argument is a int*
, not a mwSize*
:
sn = (mwSize *)mxGetData(prhs[3]);
您需要确保prhs[3]
实际上包含一个int32
矩阵,然后才能将其指针强制转换为int*
.否则,您将必须像上面一样复制数据.
You need to make sure that prhs[3]
actually contains an int32
matrix, then you can cast its pointer to a int*
. Otherwise you'll have to copy the data over like we did above.
还要仔细检查所有其他参数,以确保传递正确的类型.设置编译器以警告所有隐式强制转换,然后注意所有这些警告.这些警告中的每一个都是导致您的程序在运行时崩溃的潜在原因.全部修复!
Double-check all the other parameters too, to make sure you are passing the right types. Set up your compiler to warn you of all implicit casts, and then pay attention to all those warnings. Each of those warnings is a potential cause for your program to crash at runtime. Fix them all!
这篇关于运行MEX文件时MATLAB崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!