简体   繁体   中英

MATLAB crashes when I run MEX file

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.

You can find how we define "NNLt". And what means your "tmp" here?

std::copy(mxGetPr(tmp), mxGetPr(tmp)+N, NNLt.begin());

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;
 }

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

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.

For example,

NNLt = (vector<int> *)mxGetData(prhs[0]);

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.

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());

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!

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!

And the 4th argument is a int* , not a mwSize* :

sn = (mwSize *)mxGetData(prhs[3]); 

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM