【问题标题】:why matlab out of memory using mex为什么matlab内存不足使用mex
【发布时间】:2013-07-26 22:46:43
【问题描述】:

如果我在循环中使用 mex 文件,Matlab 会内存不足。我认为这是由内存泄漏引起的。 mxMalloc 变量被 mxFree 释放,但我无法使用 mxDestroyArray(plhs[0]) 销毁 mxCreateNumericArray 变量。

mex 文件来自 Offscreen 工具箱 link 。代码如下。

#include "mex.h"
#include "math.h"
#include "OffscreenGL.h"
#include "OffscreenCommon.h"
void drawPatchAndConvert(GLuint listName, GLubyte *imageBuffer, unsigned int imgHeight, unsigned int imgWidth, unsigned int zoomFactor = 1)
{
      // This is a temporary bug fix for Nvidia's open program
      // seems the width of the pixel has to be a multiple of 4
      // for other width, we have to pad the width and remove it later
     unsigned int paddedWidth = imgWidth * zoomFactor % 4;
     if (paddedWidth != 0){
         paddedWidth = 4 - paddedWidth + imgWidth * zoomFactor;
     }else {
        paddedWidth = imgWidth * zoomFactor;
     }

     unsigned char *paddedImgBuffer = (unsigned char *)mxMalloc(paddedWidth * imgHeight * zoomFactor * MAX_COLOR_CHANNEL * sizeof(GL_UNSIGNED_BYTE));
    drawPatch(listName, paddedImgBuffer, imgHeight, imgWidth, zoomFactor);  
    // reorder the pixel data for the opengl to matlab conversion
    unsigned int imgSize = imgHeight * imgWidth * zoomFactor * zoomFactor;
    unsigned int imgSize2 = imgSize * 2;
    unsigned int matlabImgIndex = 0;
    unsigned int oglImageIndex = 0;

    for (int j = 0; j < imgWidth * zoomFactor; j++) {
        for (int i = 0; i < imgHeight * zoomFactor; i++, matlabImgIndex++) {
            oglImageIndex = (j + (imgHeight*zoomFactor -1-i) * paddedWidth) * 3;
            imageBuffer[matlabImgIndex] = paddedImgBuffer[oglImageIndex];
            imageBuffer[matlabImgIndex + imgSize] = paddedImgBuffer[oglImageIndex + 1];
            imageBuffer[matlabImgIndex + imgSize2] = paddedImgBuffer[oglImageIndex + 2];
        }
    }
    mxFree(paddedImgBuffer);
}

static void renderColorMesh(double *FM, int fNum, double *VM, int vNum, float *ColorM, int colorNum,const mxArray *CamParamS, double *imgSizeV, double *zNearFarV, unsigned int zoomFactor,unsigned char *imgBuffer)
{
      cameraSetup(CamParamS, zNearFarV[0], zNearFarV[1], (unsigned int) imgSizeV[0],  (unsigned int) imgSizeV[1], zoomFactor);
   #ifndef NDEBUG
    mexPrintf("Start to create the display list: fNum=%d, vNum=%d, colorNum=%d\n", fNum, vNum, colorNum);
   #endif
    GLuint list = createDisplayListWithColor(FM, fNum, VM, vNum, ColorM, colorNum);

   #ifndef NDEBUG
    mexPrintf("Start to draw the patch\n");
   #endif
    drawPatchAndConvert(list, imgBuffer, (int) imgSizeV[0], (int) imgSizeV[1], zoomFactor);
}


void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
    // get the vertex array, face array, and color array
    double *FM = mxGetPr(prhs[0]);
    int fNum = mxGetM(prhs[0]); 
    double *VM = mxGetPr(prhs[1]);
    int vNum = mxGetM(prhs[1]);
    float *ColorM = (float *)mxGetData(prhs[2]);
    int colorNum = mxGetM(prhs[2]);

    // get the camera parameters
    const mxArray *CamParamS = prhs[3];
    double *imgSizeV = mxGetPr(prhs[4]);
    double *zNearFarV = mxGetPr(prhs[5]);
    double zoomFactor = mxGetScalar(prhs[6]);

    OffscreenGL offscreenGL((int)(imgSizeV[0] * zoomFactor), (int) (imgSizeV[1] * zoomFactor));
    int output3Size[3];

    unsigned char *imgBuffer;

    if (offscreenGL.RGB8Setup()) {
        //mexPrintf("OpenGLCanvas setup Successful\n");
        output3Size[0] = (int) (imgSizeV[0] * zoomFactor);
        output3Size[1] = (int) (imgSizeV[1] * zoomFactor);
        output3Size[2] = 3;

        plhs[0] = mxCreateNumericArray(3, output3Size, mxUINT8_CLASS, mxREAL);
        imgBuffer = (unsigned char *) mxGetData(plhs[0]);
        renderColorMesh(FM, fNum, VM, vNum, ColorM, colorNum, CamParamS, imgSizeV,
                        zNearFarV, (unsigned int) zoomFactor, imgBuffer);

    } else {
        mexPrintf("OpenGLCanvas setup failed\n");       
    }
}

【问题讨论】:

  • 在您显示的代码中没有调用mxDestroyArray?此外,如果您调用例如x = mxCreateNumericArray(...),则释放它的逻辑步骤是mxDestroyArray( x ) 而不是mxDestroyArray( x[ 0 ] )
  • @stijn:该行创建 MEX 函数的 LHS 输出,因此如果要将结果返回给 MATLAB,显然不应破坏。 user2613981:我没有看到任何明显的内存泄漏,我认为你使用的库是罪魁祸首,而不是你的代码......
  • 感谢您的回复。 @Amro 是对的,这不是因为这个 MEX 文件。这是因为这个文件使用了一个函数,'GLuint list = createDisplayListWithColor(FM, fNum, VM, vNum, ColorM, colorNum);'在createDisplayListWithColor的函数中是openGL的问题。 ' glColor3f(ColorM[vIndex], ColorM[vIndex + vNum], ColorM[vIndex + vNum2]); ' 但我不知道 glColor3f 是如何导致内存泄漏的。我最后用了glClear,但无法解决。
  • @user2613981:如果它解决了您的问题,您应该将其发布为答案。另一方面,当您将来遇到此类问题时,首先要尝试使用mxMalloc 而不是malloc,这样分配的内存会在 MATLAB 内存管理器中注册,并在以下情况下自动释放MEX 功能退出(以防您忘记手动 mxFree 它)
  • 好的,我刚看到你的第二条评论,也许这还没有解决。我还没有查看工具箱代码,所以我不能说那个函数的内存泄漏到底在哪里。现在我建议您附加一个调试器并逐步执行 C 代码,也许您可​​以通过这种方式发现问题...

标签: c matlab opengl memory-leaks mex


【解决方案1】:

这行很可疑:

    paddedWidth = 4 - paddedWidth + imgWidth * zoomFactor;

它只用几个字节填充整个放大线。我认为你的意思是

     paddedWidth = (4 - paddedWidth + imgWidth) * zoomFactor;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 2014-05-20
    • 1970-01-01
    • 2017-06-05
    • 1970-01-01
    • 2012-08-12
    • 1970-01-01
    相关资源
    最近更新 更多