Path: news.mathworks.com!not-for-mail
From: <HIDDEN>
Newsgroups: comp.soft-sys.matlab
Subject: Re: Inplace array (mex)
Date: Sat, 27 Jun 2009 20:27:01 +0000 (UTC)
Organization: Boeing
Lines: 120
Message-ID: <h25val$cna$1@fred.mathworks.com>
References: <h2540t$73d$1@fred.mathworks.com>
Reply-To: <HIDDEN>
NNTP-Posting-Host: webapp-03-blr.mathworks.com
Content-Type: text/plain; charset="ISO-8859-1"
Content-Transfer-Encoding: 8bit
X-Trace: fred.mathworks.com 1246134421 13034 172.30.248.38 (27 Jun 2009 20:27:01 GMT)
X-Complaints-To: news@mathworks.com
NNTP-Posting-Date: Sat, 27 Jun 2009 20:27:01 +0000 (UTC)
X-Newsreader: MATLAB Central Newsreader 756104
Xref: news.mathworks.com comp.soft-sys.matlab:551125


"Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <h2540t$73d$1@fred.mathworks.com>...
> I want to create an inplace column vector using MEX. The idea is to create a column array that has its data pointer points on the the data block of an existing (input) matrix. Everything going well until I set the data pointer. Then it crashes 
> 
> a=rand(1,7)
> 
> a =
> 
>     0.8147    0.9058    0.1270    0.9134    0.6324    0.0975    0.2785
> 
> >> b=inplacecolumn(a,3)
> 
> Am I allowed to do such thing? If not what cause the crash?

No. You cannot do this. The problem is what happens when variables get cleared. If "a" gets cleared, the MATLAB memory manager knows nothing about this shared memory with "b".  So the data memory for "a" is freed, and suddenly the "b" data pointer is pointing to invalid memory. Of course any access of this memory downstream could cause a crash.  And what happens when you clear "b", either before or after "a" is cleared? The MATLAB memory manager does not have any memory block address for allocations that match the "b" data pointer, so when it tries to check for sharing or tries to free this memory the results will be undefined, again potentially resulting in a crash.

You *can* get away with this behavior, but you have to be *very* careful to never do anything that would cause the original full data block that "b" is pointing to to be cleared before "b" is properly cleared, never do anything that would cause data sharing with "b" and another variable (e.g., assignment or reshape), and never clear "b" until you could manually detach its data pointer with another specialized mex routine. e.g., consider this mex routine called uninplacecolumn.c

/* Here is my UNINPLACECOLUMN MEX function

/*************************************************************************
 * function uninplacecolumn(a)
 * Detaches the data from an inplace column mxArray that was created
 * with the inplacecolumn function.
 ************************************************************************/
#include "mex.h"
#include "matrix.h"

#define mwSize int

/* Gateway of inplacecolumn */
void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[]) {
    
    mwSize k, N, M;
    double *Pr;
    
    /* Check arguments */
    if (nrhs!=1)
        mexErrMsgTxt("UNINPLACECOLUMN: One input argument required.");
    
    if( nlhs != 0 ) {
        mexErrMsgTxt("UNINPLACECOLUMN: Zero output arguments required.");
    }
    
    mxSetM(prhs[0], 0);
    mxSetN(prhs[0], 0);
    mxSetPr(prhs[0], NULL);
      
    return;

} /* Gateway of UNINPLACECOLUMN.c */ 

And then consider this sequence of MATLAB commands:

>> format debug
>> a=rand(3,3)
a =
Structure address = 39cd9a0 
m = 3 
n = 3
pr = 10181f60 
pi = 0
    0.9501    0.4860    0.4565
    0.2311    0.8913    0.0185
    0.6068    0.7621    0.8214
>> b=inplacecolumn(a,2)
b =
Structure address = fe74120 
m = 3 
n = 1
pr = 10181f78 
pi = 0
    0.4860
    0.8913
    0.7621
>> c=2*b
c =
Structure address = fe73560 
m = 3 
n = 1
pr = fe643e0 
pi = 0
    0.9720
    1.7826
    1.5242
>> uninplacecolumn(b)
>> b
b =
     []
>> clear b
>> a
a =
Structure address = 39cd9a0 
m = 3 
n = 3
pr = 10181f60 
pi = 0
    0.9501    0.4860    0.4565
    0.2311    0.8913    0.0185
    0.6068    0.7621    0.8214
>> c
c =
Structure address = fe73560 
m = 3 
n = 1
pr = fe643e0 
pi = 0
    0.9720
    1.7826
    1.5242
>> clear all
>> whos

This all works because 

1) I didn't clear "a" before I cleared "b"
2) I never used "b" in a way that caused data sharing with another variable
3) I detached the data pointer for "b" before I cleared "b"

James Tursa