do not understand mxSetData

Hi, I have declared a pointer to a float
float *myvariable;
I initialize this to
myvariable = mxCreateNumericMatrix(256,1,SINGLE (sorry for not the exact syntax),0);
Then I call a function func(myvariable);
This function does math on myvariable and returns the pointer.
Now if I have to output this variable, I get Matlab crash with this:
mxSetData(plhs[0],(float*)myvariable);
I have tried mxFree before the line but still a problem.
Questions: 1. If the second parameter is void according to definition how come my program compiles fine without error.
2. Why does Matlab crash (implying memory leak)?
3. The other option works and this is
plhs[0] = mxCreateNumericArray(256 matrix of SINGLE 0) and finally myvariable=mxGetData(plhs[0]); func(myvariable);
The reason I do not like this way is
a. I would prefer to run the function first and then assign the return to plhs[0];
b. It is a very ugly way of doing it like this, though it works.
c. I would at some point like to declare "myvariable" to be static so that every time it is requested by Matlab function some.m, I do not initialize it to 0. And I have many such variables to work with. I am updating data every fraction of a second for several minutes.
And I have to work with floats
Thanks

 Accepted Answer

mxCreateNumericMatrix creates a Matlab variable and returns a mxArray * pointer to it. This variable has a header, e.g. the type of the values, and contains a pointer to the actual data, see mxGetPr for a DOUBLE array or mxGetData for all other types.
mxSetData injects a pointer to the data manually to the Matlab variable. This overwrites the pointer to the existing values. If you assign an mxArray pointer to the data, a crash is expected.
You have to distinguish between the Matlab arrays and their data:
float *data;
plhs[0] = mxCreateNumericMatrix(...);
data = (float *) mxGetData(plhs[0]);
func(data);
I prefer to use Matlab arrays in the main function (mexFunction) only and call all subfunctions using the C-pointers to the underlying data. Then the mexFunction is the gateway between Matlab and C and it is easy to use the subfunctions in a pure C program also.

13 Comments

Hi Jan,
Thanks, but not clear yet.
Are you saying that values which the plhs[0] is pointing to ('NULL' in my case) are forced onto the values of the "myvariable" pointer? But if that is the case why crash? Is that because 'NULL' is not strictly initialized?
I tried this
plhs[0] = mxgetData(myvariable)
But this obviously does not work because plhs is not of type float.
So my question:
How do I assign the plhs[0] pointer to point to data that myvariable is pointing to? I cannot use mxGetpr because I am dealing with floats...
gujax
No, "plhs[0] = mxGetData(myvariable)" is again a confusion of the Matlab level and the data level of the variable. This must crash!
mxGetData replies a pointer to the raw data in the memory, while plhs[0] must be a Matlab variable, which contains a header with the type and dimensions of the variable in addition.
When plhs[0] is a pointer to NULL, it is not initialized. Any access of this variable is a NULL pointer exception then, which means a hard crash.
Please read the example C-files in the Matlab folder. Using C is much harder than using Matlab. It is trivial to compile C code successfully, which let your machine crash. It is even easier to destroy the computer, if you are low- or high-skilled enough. It is no problem in C to create an array with 5 elements and access the 6th one, or even better the element with index -1000. This is valid C and the programmer has to care for such important details.
If you are a beginner, do not use mxSetData. Create plhs[0] by mxCreateNumericMatrix and deliver the pointer to the allocated memory to the subfunction, as shown in my post. Then write directly to the array *data points to.
Clarification: in C, one "must not" access an element that does not exist; one cannot even point to an element that does not exist, except for the NULL pointer and except for it being legal to point (but not access) one element past the end of an array.
In C terms, doing something that you "must not" at runtime has undefined behavior. The operation might do something useful. The computer might halt and catch fire. Nasal daemons might appear. And there is even a possibility that you will get an error message, but you are better off playing the lottery than counting on that.
On the other hand, in C, if an object has at least 1000 elements, it is completely legal to create a pointer to the 1000'th element or later, and then to index that pointer at -1000. As long as the adjusted pointer points "inside" the object (and to an element boundary) the behavior is well defined. But if it does not point "inside" the object, then it is nasal daemon time again.
You can point to an element outside the possible address space. Anyway, I did not define the term "existence of an element" properly. I think, especially with respect to C-arrays such a definition is not trivial.
When I saw the multiplely (or multiply?) flawed:
mxSetData(plhs[0], (float*) myvariable);
I was impressed by the stubborn stability of Matlab another time.
We malign EVAL, but mxSetData can cause much more headaches.
@Jan: Not sure what you mean by "You can point to an element outside the possible address space." As Walter says, in Standard C you can only point to an array element (or one beyond but not dereference it), or to anywhere (properly aligned) within an allocated block (or one beyond etc), or the pointer can be NULL. You can't (legally) generate a pointer value outside those areas, since the behavior is not defined. E.g., the implementation might halt whenever an out-of-bounds pointer value is generated regardless of whether you try to dereference it or not. The following is technically undefined behavior even though you can usually get away with it at runtime:
int x[10];
int *y = x + 20; // undefined behavior
*(y-15) = 2; // get away with it since y-15 is inside x array
Side Note: One other thing mxSetData (and its friends) does that I don't see mentioned above is to remove the passed pointer from the garbage collection list.
@James: I meant this as an answer to Walter's "one cannot even point to an element that does not exist" an the OP's "my program compiles fine without error". You can compile an illegal pointer access succesfully, but the program will fail at runtime, of course.
My "cannot" should have been a '"must not"'. Undefined behavior.
OK (to both of you).
Walter's "must not" should be a "must not as long as you do not want to drive into troubles".
Remember that people are rolling dry leafs of toxic plants in paper, set them on fire and inhale the strange smelling combustion gas. And they pay for it.
@gujax: Three C-programmers discuss about the magic power, but is your problem solved? I've written the warnings to convince you to get C-lessons. While you can write Matlab programs after reading the Getting Started chapters of the documentation (some try it even without this), C more like a princess or a programmable chainsaw.
"Lessee ... just pull this cord here and ... VVRRRROOOOOOOMMM!! Oh #%$*&!!! ... guess I shouldn't have done that while it was sitting on the dining room table ...
Thank you all for suggestions and I have followed your advice - i.e., not play with mxSetData (though I am curious to know where it can be used. I see no examples anywhere).
I have something off from an old answer by James Tursa which prompted me to do exactly what he suggested - but my program crashed despite it.
I am not blaming James - it is likely that I must have additionally done something wrong (I was - I was not initializing plhs but neither do I see James doing it in his solution). I am just saying that his old answer to someone else's similar problem provided me with a solution - which did not work unfortunately for me and that is what prompted my question and you know the rest.
So here it is just for the sake of completion.
Re: Copying array from my DLL into mxCreateNumericArray pointer
Posted: Jan 23, 2009 2:24 PM
Ashish has already solved your problem, but I would like to point out what is wrong with your code, particularly the mxSetData calls. Here is your code snippet:
long* imageArray = 0;
unsigned int returnCode = 0;
:
imageArray = (long*)mxMalloc(arrayLength * sizeof(long));
:
returnCode = MyFunction(imageArray, arrayLength);
:
mxSetData(plhs[0], &returnCode);
mxSetData(plhs[1], &imageArray);
returnCode is a local variable, it no longer exists once mexFunction returns to MATLAB. So you can't use its memory in an mxArray. You can only use memory created with the mx___ functions in mxArray variables. What you have done will certainly access invalid memory once the mexFunction exits, possibly resulting in a seg fault at some point, because the data pointer for the return variable plhs[0] will no longer be valid once the mexFunction exits.
imageArray is already a pointer to a data area created with an mx___ function, so you are in good shape here. You just need to pass this value as the second argument. But what you have done is pass the address of the imageArray variable itself, not the address of the data it points to. This will corrupt memory. You should have done this:
mxSetData(plhs[1], imageArray);
And finally, you should be aware that mxSetData does NOT free the existing data memory before setting the new pointer values. Even if you had coded the mxSetData calls correctly, it would have resulted in a memory leak. mxSetData calls should be set up like this:
mxFree(mxGetData(plhs[0]));
mxSetData(plhs[0], whatever);
mxFree(mxGetData(plhs[1]));
mxSetData(plhs[1], whatever);
Leaking memory created with mx___ calls is garbage collected by MATLAB when mexFunction exits so usually this won't be a serious problem, but it is still bad programming practice.
Having said all that, I would again point you to Ashish's response, which contains a much better way of accomplishing your goals without resorting to mxSetData.
James Tursa
correction: Actually, I happened across James old suggestion after I had placed in my query. But I noticed that I did what was being suggested.
Also if my response sounds offending please let me know and I will delete it. I am not pointing blame at James and I must emphatically state that I had made a mistake in not initializing plhs. Once I initialize, the above code by James works fine and no more crashes - though my new code only uses mxGetData. I have shied away from setData and its ghosts. And yes - I barely program in C.
gujax
@gujax: I am never offended in the least by someone pointing out my mistakes. That is how I learn, and I like to learn. Thanks for your gracious regard for my feelings, but it is really not necessary in my case. Post anything you want. (It would not surprise me that I have some errors in my oldest posts)
Regarding what will or will not work in your case, I would suggest you post your code as you currently have it and then we can comment on it. There are subtleties of creating mxArray variables from pieces that are *not* in the documentation ... I simply had to learn them from other posters (e.g. Jan, Bruno, Walter, et al) or from trial and error on my own part. Using the mxCreateETC functions are hard enough for a beginning mex programmer to deal with without venturing into the mxSetData etc stuff, hence the wise advice from Jan to avoid it if you can ... at least for now. But post your code and we can go from there.

Sign in to comment.

More Answers (0)

Categories

Find more on Programming in Help Center and File Exchange

Asked:

on 8 Mar 2012

Community Treasure Hunt

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

Start Hunting!