Memory leak in mex file

I am working with a mex file that was leaking memory due to code below. I have tried clearing arrays using mxDestroyArray but with that Matlab got stuck:
// create cell array for returning classification result
plhs[0] = mxCreateCellMatrix((int)leafIndicesPerTree.size(),1);
// information about structure fields
mwSize dims[2] = {1,1};
const char *field_names[] = {"class","distrib","codebase","votes"};
// loop through trees and determine the winning class for each sampling point
for(int t=0; t<leafIndicesPerTree.size();t++){
//allocate matlab vector which has as many entries as there were sampling points in the test image
mxArray* currentTree = mxCreateStructArray(2, dims, 4, field_names);
mxArray* classArray = mxCreateDoubleMatrix(testData.Count(),1,mxREAL);
mxArray* distribArray = mxCreateDoubleMatrix(testData.Count(),numClasses,mxREAL);
mxArray* votesCell = mxCreateCellMatrix(testData.Count(),1);
mxArray* codebaseCell = mxCreateCellMatrix(testData.Count(),1);
// loop through all the sampling positions
for (unsigned int i=0; i<testData.Count(); i++) {
// determine classification result (bin with maximal value)
int leafIndex=leafIndicesPerTree[t][i];
StatisticsProvider result=forest->GetTree(t).GetNode(leafIndex).TrainingDataStatistics;
int winnerClass = 0;
double maxDistrib = -1;
for(int j=0;j<numClasses;j++){
if(result.getProbability(j) > maxDistrib){
winnerClass = j;
maxDistrib = result.getProbability(j);
}
}
// write winner class
double* arrayValue = mxGetPr(classArray);
arrayValue[i] = winnerClass;
// write distribution
arrayValue = mxGetPr(distribArray);
for(int c=0;c<numClasses;c++){
arrayValue[c*testData.Count()+i] = result.getProbability(c);
}
// if sampling point has been classified as foreground save votes and codebase
if(winnerClass > 0){
// get votes of winner class (votes only exist for foreground classes --> winnerClass-1)
std::vector<DataPoint> votes = result.getVotes(winnerClass-1);
// create matrix to store votes
// first column: x coordinate
// second column: y coordinate
// third column: z coordinate
// fourth column: image index
mxArray* codebaseArray = mxCreateDoubleMatrix((int)votes.size(),4,mxREAL);
double* codebaseArrayValue = mxGetPr(codebaseArray);
// create matrix to store votes
// for each vector to each object centroid there are three columns (x coordinate, y coordinate z coovotesrdinate)
mxArray* votesArray = mxCreateDoubleMatrix((int)votes.size(),(numClasses-1)*3,mxREAL);
double* votesArrayValue = mxGetPr(votesArray);
for(int v=0;v<votes.size();v++){
// extract codebase
codebaseArrayValue[v] = votes[v].getOrigPos().x+1;
codebaseArrayValue[votes.size()+v] = votes[v].getOrigPos().y+1;
codebaseArrayValue[2*votes.size()+v] = votes[v].getOrigPos().z+1;
codebaseArrayValue[3*votes.size()+v] = votes[v].getImageIndex()+1;
// extract votes
for(int c=0;c<(numClasses-1);c++){
votesArrayValue[c*3*votes.size()+v] = votes[v].getVote(c).x+1;
votesArrayValue[(c*3+1)*votes.size()+v] = votes[v].getVote(c).y+1;
votesArrayValue[(c*3+2)*votes.size()+v] = votes[v].getVote(c).z+1;
}
}
mxSetCell(codebaseCell,i,codebaseArray);
mxSetCell(votesCell,i,votesArray);
mxDestroyArray(codebaseArray);
mxDestroyArray(votesArray);
}
}
mxSetField(currentTree,0,"class",classArray);
mxSetField(currentTree,0,"distrib",distribArray);
mxSetField(currentTree,0,"votes",votesCell);
mxSetField(currentTree,0,"codebase",codebaseCell);
mxSetCell(plhs[0],t,currentTree);
mxDestroyArray(classArray);
mxDestroyArray(distribArray);
mxDestroyArray(votesCell);
mxDestroyArray(codebaseCell);
mxDestroyArray(currentTree);
}
Any idea why that could be happening?

Answers (1)

James Tursa
James Tursa on 11 Mar 2016
Edited: James Tursa on 11 Mar 2016
Sounds like you have two problems, a memory leak and MATLAB crashing. Let's clear up the MATLAB crashing first and then get back to your memory leak.
Your MATLAB crashes are caused by you doing mxDestroyArray on an mxArray that is part of a struct or cell array. You can't do that because it invalidates the memory inside the struct or cell array variable ... so when MATLAB tries to access the contents of the struct or cell array it accesses this invalid memory and bombs. Here is the basic behavior:
mxSetCell, mxSetField, and mxSetFieldByNumber have the following syntax:
void mxSetCell(mxArray *pm, mwIndex index, mxArray *pvalue);
void mxSetField(mxArray *pm, mwIndex index, const char *fieldname, mxArray *pvalue);
void mxSetFieldByNumber(mxArray *pm, mwIndex index, int fieldnumber, mxArray *pvalue);
The all do the following to pvalue:
1) Set the appropriate element of pm equal to pvalue (i.e., copy the address into the element spot ... this is not a deep copy of pvalue)
2) Change the type of pvalue to "SUB-ELEMENT" (i.e., one of the hidden fields in the mxArray variable itself gets changed to indicate it is part of a struct or cell array)
3) The address pvalue gets removed from the garbage collection list.
So the disposition of pvalue is now tied to the struct or cell array that it is now part of. When this struct or cell array gets deep destroyed, all of the elements (the mxArray variables that are the elements) get automatically deep destroyed as well.
Also, you cannot re-use a pvalue in multiple mxSetCell, mxSetField, or mxSetFieldByNumber calls because when MATLAB tries to deep destroy the struct or cell array it will try to destory the pvalue multiple times, causing a crash (accessing memory that was invalidated with the first destroy of pvalue). Now, this advice is based on the official API functions that are available to you. But in fact there is a way to re-use the pvalue mxArray variables inside of struct and cell arrays using non-standard methods (unofficial API functions or hacking into the mxArray) ... but I won't publish that info here since it is a bit off-topic to your problem.
BOTTOM LINE: Get rid of all those mxDestroyArray calls that are used on struct or cell array contents!
E.g.,
mxSetCell(codebaseCell,i,codebaseArray);
mxSetCell(votesCell,i,votesArray);
mxDestroyArray(codebaseArray); <-- This will crash MATLAB
mxDestroyArray(votesArray); <-- This will crash MATLAB
And,
mxSetField(currentTree,0,"class",classArray);
mxSetField(currentTree,0,"distrib",distribArray);
mxSetField(currentTree,0,"votes",votesCell);
mxSetField(currentTree,0,"codebase",codebaseCell);
mxSetCell(plhs[0],t,currentTree);
mxDestroyArray(classArray); <-- This will crash MATLAB
mxDestroyArray(distribArray); <-- This will crash MATLAB
mxDestroyArray(votesCell); <-- This will crash MATLAB
mxDestroyArray(codebaseCell); <-- This will crash MATLAB
mxDestroyArray(currentTree); <-- This will crash MATLAB
Once you clear up all of this mxDestroyArray crashing stuff, then we can get back to your original problem of a memory leak.

4 Comments

Thank you for your detailed response. I have removed the mxDestroyArray but now my memory leak is back as it was. How do I solve that?
after removing mxDestroArray, other than memory leak, matlab also crashed with this error:
(MATLAB:5518): GLib-WARNING **: unknown option bit(s) set
** (MATLAB:5518): WARNING **: Compilation of mdvd regex failed: Error while compiling regular expression ^\{[0-9]+\}\{[0-9]+\} at char 0: unknown option bit(s) set
(MATLAB:5518): GLib-WARNING **: unknown option bit(s) set
** (MATLAB:5518): WARNING **: Compilation of subrip regex failed: Error while compiling regular expression ^ {0,3}[ 0-9]{1,4}\s*(\u000d)?
?[0-9]{1,2}: ?[0-9]{1,2}: ?[0-9]{1,2}[,.] {0,2}[0-9]{1,3} +--> +[0-9]{1,2}: ?[0-9]{1,2}: ?[0-9]{1,2}[,.] {0,2}[0-9]{1,2} at char 0: unknown option bit(s) set
(MATLAB:5518): GLib-WARNING **: unknown option bit(s) set
** (MATLAB:5518): WARNING **: Compilation of dks regex failed: Error while compiling regular expression ^\[[0-9]+:[0-9]+:[0-9]+\].* at char 0: unknown option bit(s) set
(MATLAB:5518): GLib-CRITICAL **: g_regex_match_full: assertion 'regex != NULL' failed
(MATLAB:5518): GLib-CRITICAL **: g_regex_match_full: assertion 'regex != NULL' failed
(MATLAB:5518): GLib-CRITICAL **: g_regex_match_full: assertion 'regex != NULL' failed
(MATLAB:5518): GLib-CRITICAL **: g_regex_match_full: assertion 'regex != NULL' failed
(MATLAB:5518): GLib-CRITICAL **: g_regex_match_full: assertion 'regex != NULL' failed
(MATLAB:5518): GLib-CRITICAL **: g_regex_match_full: assertion 'regex != NULL' failed
*** Error in `/usr/local/MATLAB/R2015b/bin/glnxa64/MATLAB': corrupted double-linked list: 0x00007f42b92c5b70 ***
Can you re-post your current code?
// instanciate the DataPointCollection (takes care of all the training data)
DataManager testData = DataManager(meshGridSampling,meshGridFeatures,testImage, numClasses);
// load tree
auto_ptr<Forest<AxisAlignedFeatureResponse, StatisticsProvider>> forest
= Forest<AxisAlignedFeatureResponse, StatisticsProvider>::Deserialize(loadingPath);
// apply tree to test image
std::vector<std::vector<int>> leafIndicesPerTree;
forest->Apply(testData,leafIndicesPerTree);
//-----------------------------------------------------------
// write classification result into an mxArray
//-----------------------------------------------------------
// create cell array for returning classification result
plhs[0] = mxCreateCellMatrix((int)leafIndicesPerTree.size(),1);
// information about structure fields
mwSize dims[2] = {1,1};
const char *field_names[] = {"class","distrib","codebase","votes"};
// loop through trees and determine the winning class for each sampling point
for(int t=0; t<leafIndicesPerTree.size();t++){
//allocate matlab vector which has as many entries as there were sampling points in the test image
mxArray* currentTree = mxCreateStructArray(2, dims, 4, field_names);
mxArray* classArray = mxCreateDoubleMatrix(testData.Count(),1,mxREAL);
mxArray* distribArray = mxCreateDoubleMatrix(testData.Count(),numClasses,mxREAL);
mxArray* votesCell = mxCreateCellMatrix(testData.Count(),1);
mxArray* codebaseCell = mxCreateCellMatrix(testData.Count(),1);
// loop through all the sampling positions
for (unsigned int i=0; i<testData.Count(); i++) {
// determine classification result (bin with maximal value)
int leafIndex=leafIndicesPerTree[t][i];
StatisticsProvider result=forest->GetTree(t).GetNode(leafIndex).TrainingDataStatistics;
int winnerClass = 0;
double maxDistrib = -1;
for(int j=0;j<numClasses;j++){
if(result.getProbability(j) > maxDistrib){
winnerClass = j;
maxDistrib = result.getProbability(j);
}
}
// write winner class
double* arrayValue = mxGetPr(classArray);
arrayValue[i] = winnerClass;
// write distribution
arrayValue = mxGetPr(distribArray);
for(int c=0;c<numClasses;c++){
arrayValue[c*testData.Count()+i] = result.getProbability(c);
}
// if sampling point has been classified as foreground save votes and codebase
if(winnerClass > 0){
// get votes of winner class (votes only exist for foreground classes --> winnerClass-1)
std::vector<DataPoint> votes = result.getVotes(winnerClass-1);
// create matrix to store votes
// first column: x coordinate
// second column: y coordinate
// third column: z coordinate
// fourth column: image index
mxArray* codebaseArray = mxCreateDoubleMatrix((int)votes.size(),4,mxREAL);
double* codebaseArrayValue = mxGetPr(codebaseArray);
// create matrix to store votes
// for each vector to each object centroid there are three columns (x coordinate, y coordinate z coovotesrdinate)
mxArray* votesArray = mxCreateDoubleMatrix((int)votes.size(),(numClasses-1)*3,mxREAL);
double* votesArrayValue = mxGetPr(votesArray);
for(int v=0;v<votes.size();v++){
// extract codebase
codebaseArrayValue[v] = votes[v].getOrigPos().x+1;
codebaseArrayValue[votes.size()+v] = votes[v].getOrigPos().y+1;
codebaseArrayValue[2*votes.size()+v] = votes[v].getOrigPos().z+1;
codebaseArrayValue[3*votes.size()+v] = votes[v].getImageIndex()+1;
// extract votes
for(int c=0;c<(numClasses-1);c++){
votesArrayValue[c*3*votes.size()+v] = votes[v].getVote(c).x+1;
votesArrayValue[(c*3+1)*votes.size()+v] = votes[v].getVote(c).y+1;
votesArrayValue[(c*3+2)*votes.size()+v] = votes[v].getVote(c).z+1;
}
}
mxSetCell(codebaseCell,i,codebaseArray);
mxSetCell(votesCell,i,votesArray);
}
}
mxSetField(currentTree,0,"class",classArray);
mxSetField(currentTree,0,"distrib",distribArray);
mxSetField(currentTree,0,"votes",votesCell);
mxSetField(currentTree,0,"codebase",codebaseCell);
mxSetCell(plhs[0],t,currentTree);
}
}

Sign in to comment.

Categories

Asked:

on 11 Mar 2016

Commented:

on 12 Mar 2016

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!