Skip to content

.Call setAttrib(ans,R_DimSymbol,dim); Crashes.

3 messages · Wolski, Douglas Bates

#
Hi!


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?

Sincerely Eryk.
Windows 2000
R 1.8.1
#
"wolski" <wolski at molgen.mpg.de> writes:
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 cs.wisc.edu> writes:
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).