运行MEX文件时MATLAB崩溃 [英] MATLAB crashes when I run MEX file

查看:423
本文介绍了运行MEX文件时MATLAB崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个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!

还请注意,第三个参数Fbvector<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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆