From: Robert on
Hey,

So my goal essentially boils down to deleting the first row and last of an array. (I'm trying to create a "window" type function)

the code I would like to use is as follows:

mxArray* dataIn = mxDuplicateArray(prhs[1]);

mxSetPr(dataIn,mxGetPr(dataIn)+1);

mxSetM(dataIn,mxGetM(dataIn)-1)

In R2008b this seems to work fine. In R2009b, however, this throws an error (it may in R2009a as well, I didn't have a copy available to test it though).

I could simply use memcpy or memmove instead of mxSetPr and the pointer arithmetic, but since the plan is to do this repeatedly, this creates as significant performance issue for me.

Thanks in advance for any help you can provide.
From: James Tursa on
"Robert" <rtaintor(a)hotmail.com> wrote in message <hpgrdt$rqf$1(a)fred.mathworks.com>...
> Hey,
>
> So my goal essentially boils down to deleting the first row and last of an array. (I'm trying to create a "window" type function)
>
> the code I would like to use is as follows:
>
> mxArray* dataIn = mxDuplicateArray(prhs[1]);
>
> mxSetPr(dataIn,mxGetPr(dataIn)+1);
>
> mxSetM(dataIn,mxGetM(dataIn)-1)
>
> In R2008b this seems to work fine. In R2009b, however, this throws an error (it may in R2009a as well, I didn't have a copy available to test it though).
>
> I could simply use memcpy or memmove instead of mxSetPr and the pointer arithmetic, but since the plan is to do this repeatedly, this creates as significant performance issue for me.
>
> Thanks in advance for any help you can provide.

The technique you describe will *never* be reliable in any version of MATLAB. Whenever you allocate memory with one of the mx___ functions such as mxDuplicateArray, mxCreate___, mxMalloc, etc. the MATLAB memory manager logs the memory so it knows about it. And although I am not 100% sure since it is proprietary, I am assuming that it logs it based on the starting address of the memory block. When it frees the memory, it does so based on that starting address of the memory block. What you have done is to put an address into the mxArray pr area that does not correspond to any starting block ... it is one in the middle of the block. So when MATLAB eventually gets around to destroying this mxArray it will try to free that memory block and likely pass that middle address to a free() or similar function in the background. Passing addresses to free() functions that were not generated by one of
the associated allocation functions yields unpredictable results. Yeah, it may look like it works for awhile, or in a certain version of MATLAB, but then strange things start to happen, or it doesn't work in another version, etc. You should not do this. You can never be certain it will work. There *is* a way to do it but you really have to know what you are doing and be very careful. First, never forget the starting address ... save it somewhere. Then after you reset the pr pointer to somewhere in the middle, never do anything with this mxArray that will cause it to share memory with another mxArray (which if it happened would cause MATLAB to eventually try to free this block from the middle address with unpredictable results), and then manually reset the pr pointer to the original starting address before calling mxDestroyArray on it (or manually call mxFree with the original
address, then call mxSetPr with a NULL pointer and then call mxDestroyArray on the mxArray).

What are you using this mxArray for? Maybe there is another way to accomplish your goals without this dangerous trickery. For instance, deleting the last column of an mxArray is simple and safe just by calling mxSetN with an N that is one less than the original. Since the base address of the pr area in the mxArray is still intact it won't matter if it is shared with another array ... it can still always be safely destroyed with mxDestroyArray. Maybe something like this could work for you if you reorganize your problem as columns instead of rows.

James Tursa
From: James Tursa on
"Robert" <rtaintor(a)hotmail.com> wrote in message <hpgrdt$rqf$1(a)fred.mathworks.com>...
> Hey,
>
> So my goal essentially boils down to deleting the first row and last of an array. (I'm trying to create a "window" type function)
>
> the code I would like to use is as follows:
>
> mxArray* dataIn = mxDuplicateArray(prhs[1]);
>
> mxSetPr(dataIn,mxGetPr(dataIn)+1);
>
> mxSetM(dataIn,mxGetM(dataIn)-1)
>

After looking at your code more closely this cannot possibly work. The data for the first row is interleaved in memory with the other rows ... you cannot delete it by simply resetting a pointer, you *must* copy the data in pieces in addition to resetting the array sizes. There is no way around it if you want to make an mxArray with one less row. As mentioned in my previous post, a variation of this could be made to work for deleting columns, but it will *never* work for deleting rows because of the interleaved data issue.

James Tursa
From: Robert on
Thanks for the reply!

Columns and rows are not the issue as I'm happy to switch to whichever works. This is all one dimensional data so deleting rows has worked fine.

In previous versions it had worked, and you are correct I had to be careful to keep track of how far I had moved the pointer, then move the pointer back at the end of the function. In this version however, it crashes on the call to mxSetPr (I discovered this using a visual studio debugger). My assumption was that an extra check had been placed somewhere or something. Though I understand why you're not supposed to do what I'm doing.

I was using mxArray because I want to do a matlab call to a user inputted function. Essentially this functions goes down that data and pulls out very specific "windows" of the vector and applies your function to it.

So essentially you are not allowed to move the pointer of something made by a function like mxCalloc and still use mxSetPr? This implies that matlab actually keeps track of the top of the pointers it allocates I guess?

Thanks again for your swift reply!

"James Tursa" <aclassyguy_with_a_k_not_a_c(a)hotmail.com> wrote in message <hph0dp$5dl$1(a)fred.mathworks.com>...
> "Robert" <rtaintor(a)hotmail.com> wrote in message <hpgrdt$rqf$1(a)fred.mathworks.com>...
> > Hey,
> >
> > So my goal essentially boils down to deleting the first row and last of an array. (I'm trying to create a "window" type function)
> >
> > the code I would like to use is as follows:
> >
> > mxArray* dataIn = mxDuplicateArray(prhs[1]);
> >
> > mxSetPr(dataIn,mxGetPr(dataIn)+1);
> >
> > mxSetM(dataIn,mxGetM(dataIn)-1)
> >
>
> After looking at your code more closely this cannot possibly work. The data for the first row is interleaved in memory with the other rows ... you cannot delete it by simply resetting a pointer, you *must* copy the data in pieces in addition to resetting the array sizes. There is no way around it if you want to make an mxArray with one less row. As mentioned in my previous post, a variation of this could be made to work for deleting columns, but it will *never* work for deleting rows because of the interleaved data issue.
>
> James Tursa
From: James Tursa on
"Robert" <rtaintor(a)hotmail.com> wrote in message <hpi0d5$8jv$1(a)fred.mathworks.com>...
> Thanks for the reply!
>
> Columns and rows are not the issue as I'm happy to switch to whichever works. This is all one dimensional data so deleting rows has worked fine.

Ah. Yes, one dimensional data you can do it.

> In previous versions it had worked, and you are correct I had to be careful to keep track of how far I had moved the pointer, then move the pointer back at the end of the function. In this version however, it crashes on the call to mxSetPr (I discovered this using a visual studio debugger). My assumption was that an extra check had been placed somewhere or something. Though I understand why you're not supposed to do what I'm doing.

Yes again. I believe that in later versions of MATLAB the API makes extra checks on the inputs to make sure it matches one of the starting addresses from a block allocated by the MATLAB memory manager. You *can* get around this by using the mxArray tag structure definition directly and setting pr with a direct assignment instead of using the mxGetPr function. This mxArray tag was published by Peter Boettcher on a website somewhere (can't find it at the moment).

James Tursa