"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);
It is a matter of taste whether you prefer to assign the component
then select it or to allocate the component by itself and remember to
PROTECT and UNPROTECT it. Both are a bit tedious but I find the
former to be less error-prone.
If you look at the C sources for the new Matrix_0.6 package (in the
1.9 contributed section on CRAN) you will see that just about every C
function that returns an SEXP ends with
UNPROTECT(1);
return ans;
--
Douglas Bates bates at stat.wisc.edu
Statistics Department 608/262-2598
University of Wisconsin - Madison http://www.stat.wisc.edu/~bates/