[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