Why do I get Access Violation Error while deleting arrays using mxdestroyarray to cleanup memory?

I would like to create a struct array of double and String data type and copy this array to MAT file using matputvariable.
I am able to copy double and String data successfully.
However, when I copy struct array, I get empty values in struct, and my C program also throws Access Violation Exception.
I tried both _*mxSetField*_ and _*mxsetfieldbynumber.*_
My code is below-
#include <stdio.h>
#include <string> /* For strcmp() */
#include <stdlib.h> /* For EXIT_FAILURE, EXIT_SUCCESS */
#include "mat.h"
#include "Source.h"
#define BUFSIZE 256
using namespace System::Runtime::InteropServices;
using namespace std;
struct phonebook
{
const char *m_string;
double m_double;
};
typedef struct phonebook phoneStruct;
int Flat_Struct_2Matfile(phoneStruct* str1, string& matFName_str, string& matMatTName_str){
try
{
MATFile *fp;
mxArray *mp, *mp1, *mp2, *mp3, *strp;
int i = 0;// The loop index for rows
int j = 0;// The loop index for columns
int status = -1;// The return status
char *host_eol = "\r\n";
const int tagsize = 256;
char fname[tagsize];// Filename
char matTName[tagsize];// Variable name
double *temp_buf;// Temporary double matrix
const char* matFName = matFName_str.c_str();
const char* matMatTName = matMatTName_str.c_str();
// open the mat file.
if (!(fp = matOpen(fname, "u"))) {// Open the matfile for update
// If it fails, we assume the
// file doesn't exist and open
// it for writing. (Update will
// not create a file, write
// will).
if (!(fp = matOpen(fname, "w"))) {
fprintf(stdout, "Flat_Struct_2Matfile: Unable to open %s "
"for update or write.%s", fname, host_eol);
status = -1;// If not, get out.
return status;
}
}
// Now we have to create a structure in Matlab.
const char *field_names[] = { "m_string", "m_double" };
int NUMBER_OF_FIELDS = 2;
int NUMBER_OF_STRUCTS = 2;
mwSize dims[2] = { 1, NUMBER_OF_STRUCTS };
int m_string_field, m_double_field;
strp = mxCreateStructArray(2, dims, NUMBER_OF_FIELDS, field_names);
m_string_field = mxGetFieldNumber(strp, "m_string");
m_double_field = mxGetFieldNumber(strp, "m_double");
mp1 = mxCreateDoubleMatrix(1, 1, mxREAL);
*mxGetPr(mp1) = str1->m_double;
matPutVariable(fp, "my_struct1_doub", mp1);
mxSetField(strp, 0, "m_double", mp1);
//mxSetFieldByNumber(strp, 0, m_double_field, mp1);
const char* s1 = str1->m_string;
mp2 = mxCreateString(s1);
matPutVariable(fp, "my_struct1_string", mp2);
mxSetField(strp, 0, "m_string", mp2);
//mxSetFieldByNumber(strp, 0, m_string_field, mp2);
matPutVariable(fp, matTName, strp);
mxDestroyArray(mp1);
mxDestroyArray(mp2);
mxDestroyArray(strp);
matClose(fp);
status = 0;
return status;
}
catch (...)
{
printf("Exception is thrown in struct2mat()");
}
}
int main() {
try
{
MATFile *pmat;
//const char *file = "mattest.mat";
char str[BUFSIZE];
int status;
phoneStruct struct1;
struct1.m_double = 22;
struct1.m_string = "Hi there";
string fname = "mattest.mat";
string tname = "blah";
Flat_Struct_2Matfile(&struct1, fname, tname);
}
catch (...)
{
printf("Exception is thrown in main()");
}
printf("Done\n");
return(EXIT_SUCCESS);
}
How can I fix this?
 

 Accepted Answer

The reason why the struct fields are empty and there are Access Violation Exception in the code is because you are freeing same memory twice.
mxdestroyarray deallocates the memory occupied by the specified _mxArray_ including Fields of structure arrays as well.
So, when you deallocate memory occupied by struct pointer _strp_-
mxDestroyArray(strp);
It not only deallocates memory occupied by _strp_, but also _mp1_ and _mp2_.
And, calling _mxDestroyArray_ for those _mxArray_ will cause Access Violation.
mxDestroyArray(mp1);
mxDestroyArray(mp2);
Moreover, if you clear memory used by mp1 and mp2, before writing data to MAT file using _matPutVariable_, it will write empty field values as the memory has already been destroyed-
mxDestroyArray(mp1);
mxDestroyArray(mp2);
matPutVariable(fp, matTName, strp);
The <https://www.mathworks.com/help/matlab/apiref/mxdestroyarray.html mxdestroyarray> document explains this-
mxDestroyArray deallocates the memory occupied by the specified mxArray including: * Characteristics fields of the mxArray, such as size (m and n) and type. * Associated data arrays, such as pr and pi for complex arrays, and ir and jc for sparse arrays. * Fields of structure arrays. * Cells of cell arrays.
Moreover, it is specified in the <https://www.mathworks.com/help/matlab/apiref/mxsetfieldbynumber.html mxsetfieldbynumber> and <https://www.mathworks.com/help/matlab/apiref/mxsetfield.html mxsetfield> doc pages not to deallocate memory for struct values.
To free memory for structures created using this function, call mxDestroyArray only on the structure array. Do not call mxDestroyArray on the array pvalue points to. If you do, then MATLAB attempts to free the same memory twice, which can corrupt memory.
You can verify that ny removing mxDestroyArray() on mp1 and mp2.
It will fix the issue and you will successfully write struct data to MAT file using both _*mxSetField*_ and _*mxsetfieldbynumber.*_
Hope this helps!

More Answers (0)

Products

Release

R2014a

Community Treasure Hunt

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

Start Hunting!