[R] .Call setAttrib(ans,R_DimSymbol,dim); Crashes.

Douglas Bates bates at stat.wisc.edu
Wed Feb 11 21:07:42 CET 2004


Douglas Bates <bates at cs.wisc.edu> writes:

> "wolski" <wolski at molgen.mpg.de> writes:
> 
> > I want to return a matrix. The code does the R interfacing.  This
> > version does it fine.
> > 
> >   SEXP ans,dim;
> >   PROTECT(ans = NEW_NUMERIC(count*2));
> >   memcpy(NUMERIC_POINTER(ans),result,count*sizeof(double));
> >   memcpy(&(NUMERIC_POINTER(ans)[count]),occur,count*sizeof(double));
> > /**  PROTECT(dim=NEW_INTEGER(2));
> >     INTEGER_POINTER(dim)[0]=2;
> >    INTEGER_POINTER(dim)[1]=count; 
> >    setAttrib(ans,R_DimSymbol,dim); 
> > */
> >   UNPROTECT(7);
> > 
> > If I uncomment the lines 5 to 8 than all is working fine four small
> > count's (tested 10,20).  But if the result is an array with about
> > 2000 entries R crashes vicious and violently with the lax comment
> > 
> > Process R trace trap at Wed Feb 11 13:55:45 2004
> > 
> > Anyone is seeiing something what I can not see?
> 
> In most cases it is easier to use allocMatrix instead of assigning a
> dimension attribute to a numeric vector.  You could write this as
> 
>    SEXP ans = PROTECT(allocMatrix(REALSXP, 2, count));
>    memcpy(NUMERIC_POINTER(ans),result,count*sizeof(double));
>    memcpy(&(NUMERIC_POINTER(ans)[count]),occur,count*sizeof(double));
>    UNPROTECT(1);
> 
> Another enhancement is use Memcpy, as in
> 
>    SEXP ans = PROTECT(allocMatrix(REALSXP, 2, count));
>    double *ansp = REAL(ans);    /* same as NUMERIC_POINTER(ans) */
> 
>    Memcpy(ansp, result, count);
>    Memcpy(ansp + count, occur, count);
>    UNPROTECT(1);
> 
> Regarding your particular problem, did you happen to change the
> argument to UNPROTECT when you changed the code?  You may be getting a
> stack imbalance if you change the number of PROTECTs that are executed
> and don't change the UNPROTECT count.
> 
> This is why I generally try to write C functions with only one PROTECT
> in then.  Because PROTECTing an object also PROTECTs all components
> reachable from that object I allocate other storage as components of
> the (PROTECT'ed) result then manipulate those components.  For
> example, if I don't use allocMatrix I would write what you did as
> 
>    SEXP ans = PROTECT(NEW_NUMERIC(count * 2));
>    double *ansp = NUMERIC_POINTER(ans);
>    int *dims;
> 
>    Memcpy(ansp, result, count);
>    Memcpy(ansp + count, occur, count);
>    setAttrib(ans, R_DimSymbol, NEW_INTEGER(2));
>    dims = INTEGER_POINTER(getAttrib(ans, R_DimSymbol));
>    dims[0] = 2;
>    dims[1] = count;
>    UNPROTECT(1);

By the way, you probably have the dimensions backwards here.  Recall
that R stores matrices in column-major ordering so you probably want
the dimensions to be (count, 2) not (2, count).




More information about the R-help mailing list