persistent mxArray untill matlab exits wtih Dll

4 views (last 30 days)
I exported a double* (Status) from a Dll and then I do the following in a mex file;
plhs[0] = mxCreateDoubleMatrix(10, 1, mxREAL);
Status = mxGetPr(plhs[0]);
This works very nice, untill I call this function the second time. Then my computer crashes (not immediately however) with a blue screen;
As an alternative I changed the code to the following;
//allocate persistent memory for status pointer
if (Status == NULL){ //if status is empty
plhs[0] = mxCreateDoubleMatrix(10, 1, mxREAL);
Status = mxGetPr(plhs[0]);
} else {
mxSetPr(plhs[0], Status);//if status is not empty
}
Now I can call this function over and over.
This indicates that the mxArray I allocated with mxCreateDoubleMatrix is persistent as long as matlab runs.
I'm surprised because because I would have thought that matlab would clear the old memory when the pointer (Status) points to a newly allocated array. (maybe it tries en then everything go's haywire?).
Is my interpretation correct that as long as the exported pointer points to a matlab mxArry it will be persistent, and stay that way untill I exit matlab?
  8 Comments
Chris van der Togt
Chris van der Togt on 20 Apr 2011
Yes, but this does not explain why I get a segmentation error when I don't call "clear all" before I allocate and set the mxArray pointer to Status the second time.
Kaustubha Govind
Kaustubha Govind on 21 Apr 2011
I'm not entirely clear on how you assign the global variable from a call to the MEX-file - could you clarify on that? The symptom seems to suggest a memory leak however.

Sign in to comment.

Answers (2)

Kaustubha Govind
Kaustubha Govind on 18 Apr 2011
I would expect your original code to work (unless your external library somehow re-allocates the memory pointed to by Status) - I'm assuming that by "I exported a double* (Status) from a Dll", you mean that you pass Status into the library - please correct me if I'm wrong. If so, like James said, there might be some other bug in your code causing the crash. A good place to start would be to step through the MEX-function and find the cause for the issue: http://www.mathworks.com/support/tech-notes/1600/1605.html#gen_debugging
In general, you need mexMakeArrayPersistent to declare persistent mxArrays (see example here: http://www.mathworks.com/help/techdoc/matlab_external/f25255.html#f26136).
Regarding your use of (Status == NULL) - even if MATLAB clears the memory that Status previous pointed to - the onus of setting Status to NULL is on you. Therefore, my explanation is that you are pointing to stale memory.
I would recommend using the previously cited examples to use persistent data. Note that you cannot make plhs persistent - declare a static mxArray pointer instead (again, as in the example).
  5 Comments
Chris van der Togt
Chris van der Togt on 19 Apr 2011
Your example demonstrates that it may not be sufficient to test if the pointer is NULL or not.
However,
if the pointer had been destroyed I suppose my Dll would not be able to write data to this memory without SegVs occurring. After mxSetPr(plhs[0], Status) is set the second time this function is called I can still read out values in the matlab workspace without matlab complaining. I've been able to call this function over and over with out any problem, so I think matlab has lost control over this piece of memory, once a persistent pointer in DLL memory points to it and fails to destroy it.
It is difficult to say whether there was something else in my code that could have caused the blue screen. Reusing the pointer solved this issue, but clearly you disagree with this solution.
James Tursa
James Tursa on 20 Apr 2011
Technically, you can't test the pointer *at all* once the memory it points to is freed. Doing so is non-conforming. The only thing you can legally do is assign it a new valid value.

Sign in to comment.


James Tursa
James Tursa on 20 Apr 2011
Thanks for posting more of your code. Are you statically linking to a lib file? Otherwise I don't see in your posted code how your "dll" is getting npers and vice-versa. Maybe you didn't post that part?
Here are some specific comments about your posted code:
/////setpers.cpp
As soon as setpers returns to MATLAB you are at the mercy of when the returned variable gets destroyed or modified in the calling workspace. As soon as that happens your npers pointer will no longer be valid, and any further use could crash MATLAB. This memory is NOT persistent ... it is simply hanging around as long as the calling routine does not clear it. This is not good to rely on unless you are very careful about not clearing or modifying it in the calling workspace. That is, you must not do anything that would cause MATLAB to clear the memory associated with npers.
/////resetpers.cpp
As near as I can tell the if(npers == NULL) test is pretty much useless. Since you don't set npers to NULL anywhere in your posted code (is this done somewhere else?) this test will either test against an uninitialized value (non-conforming, unpredictable results), an invalid value if the memory has been cleared already (non-conforming, unpredictable results), or it will pass. This is not good. The value of npers doesn't tell you anything about the validity of the memory it points to.
And then this line:
mxSetPr(plhs[0], npers);
will probably crash MATLAB since you don't create plhs[0] in this mex routine before you try to set its pr pointer. And a side note that even if you did you would have a temporary memory leak since mxSetPr doesn't free the old memory first.
/// runpers.cpp
Not at all clear how this mex routine (and the others) are actually getting npers from the dll.
------------------------
It appears you are attempting to simply create some persistent memory for your dll to work with via several mex routines. In that case I would advise that you simply create it using one of the MATLAB API routines, make it persistent with mexMakeArrayPersistent or mexMakeMemoryPersistent as appropriate (and remember the pointers in some global variable in the mex routine), and then lock your mex routine with mexLock. Then register a mexAtExit function so that you can clean it up when desired. That will ensure that the memory is valid throughout your processing and you have direct control over when it gets cleared. When the mex function gets cleared your registered mexAtExit function can destroy/free the memory that was made persistent. I find it simpler to put all of this functionality inside one mex routine and then call it with various options.
Do you need to have this memory/variable available in the caller workspace? I don't really have a clear picture of what your needs are. If so, then you may want to consider returning a shared data copy of the variable back to the MATLAB workspace. That way you can maintain the validity of the memory that the dll is accessing and nothing bad will happen if the caller modifies the returned variable in any way.
  4 Comments
Chris van der Togt
Chris van der Togt on 21 Apr 2011
Ah I see you have missed the point. I am not statically linking. There are two types of lib files. One for statically linking and another for dynamic linking. For dynamic linking the lib file tells the linker from which Dll the fuctions should be exported. When a mex file uses one of these functions the Dll is loaded in the matlab process memory and has its own memoroy space which is shared across all functions accessing the dll.
This means that a global pointer in the Dll is global for all mex files accessing the Dll.
And it evidently works.
This is how I compile;
After making the Dll and the lib file.
mex -LC:\librarydir\pers -lpers setpers.cpp
and
mex -LC:\librarydir\pers -lpers runpers.cpp
James Tursa
James Tursa on 21 Apr 2011
OK, thanks for clearing that up. I think I finally understand how you are building and linking all of this together. You are doing a DLL build (not a static LIB build) and then linking to the produced .lib file from the DLL build. Now back to your code ...
I still don't see where npers ever gets set to NULL, so how does your code ever know when the pointer is invalid? e.g., if you clear the variable that npers is associated with in the workspace and then call resetpers it looks like your code will bomb.
The resetpers.cpp as posted will bomb if npers is not NULL. You call mxSetPr(plhs[0],npers) but you haven't created plhs[0] in that branch. What is the resetpers function supposed to be doing? i.e., under what conditions is this function supposed to be called? Are you calling resetpers after clearing the original variable from the MATLAB workspace, or what?

Sign in to comment.

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!