[Rd] segfault

Peter Dalgaard BSA p.dalgaard@pubhealth.ku.dk
22 Feb 2001 23:37:18 +0100


Paul Gilbert <gilb@home.com> writes:

> >The actual bug is probably somewhat prior to this. If you do a "bt"
> >(backtrace) and go "up" a couple of times, you might find a spot where
> >someone forgot to PROTECT() a newly created R object.
> 
> Well ddd  still does not install the innocent with the knowlege of C
> programmers so I am guessing a bit about exactly what I should be
> looking for. If I do "up" a few times I see a section of main/dotcode.c
> starting at line 180 (copied below) that looks like it might have a
> problem. The first few cases do not have any PROTECT statements and
> others do. If this is not a a good guess then perhaps someone could fill
> me in on what statements that create new R objects look like.

Briefly (and this'll have to be brief or I'll end up writing a
book...) things like allocVector create a new objects. As long as such
an object is "loose" - not assigned to an environment or made part of
an object which is - it is in danger of being destroyed by the garbage
collector. However, the garbage collector is not called randomly, it
can only happen when memory for a new object is being allocated. 

In the first handful of cases below, one allocates a vector and stuffs
some preexisting values into it (sitting in iptr, sptr, rptr,....) and
then passes s onto something else (it is the return value of
CPtrToRObj and that only gets called from do_dotCode where the return
value gets protected eventually)

However, in the STRSXP case, s needs protection because of the
mkChar(buf) which will allocate memory, and hence the construction:

     PROTECT(s = allocVector(type, 1));
     SET_STRING_ELT(s, 0, mkChar(buf));
     UNPROTECT(1);

I don't think this stretch of code is the culprit - it is a far too
busy area to be likely to have major bugs of this caliber.

Actually, once do_dotCode is involved, I'd suspect array overruns
rather than PROTECT bugs. I've seen several cases where a vector
turned out to getting passed with the wrong length or the wrong type.
Be very careful that all arguments to .Fortran/.C are explicitly
coerced to the right type - if you forget an as.double you might get a
routine that works impeccably until someone passes something like 1:12
(which has storage mode "integer") as an argument.

> Thanks,
> Paul
> _____
>     case INTSXP:
>  s = allocVector(type, n);
>  iptr = (int*)p;
>  for(i=0 ; i<n ; i++) {
>      INTEGER(s)[i] = iptr[i];
>  }
>  break;
>     case REALSXP:
>  s = allocVector(type, n);
>  if(asLogical(getAttrib(arg, CSingSymbol)) == 1) {
>      sptr = (float*) p;
>      for(i=0 ; i<n ; i++) REAL(s)[i] = (double) sptr[i];
>  } else {
>      rptr = (double*) p;
>      for(i=0 ; i<n ; i++) REAL(s)[i] = rptr[i];
>  }
>  break;
>     case CPLXSXP:
>  s = allocVector(type, n);
>  zptr = (Rcomplex*)p;
>  for(i=0 ; i<n ; i++) {
>      COMPLEX(s)[i] = zptr[i];
>  }
>  break;
>     case STRSXP:
>  if(Fort) {
>      /* only return one string: warned on the R -> Fortran step */
>      strncpy(buf, (char*)p, 255);
>      buf[256] = '\0';
>      PROTECT(s = allocVector(type, 1));
>      SET_STRING_ELT(s, 0, mkChar(buf));
>      UNPROTECT(1);
>  } else ...
> 
> 

-- 
   O__  ---- Peter Dalgaard             Blegdamsvej 3  
  c/ /'_ --- Dept. of Biostatistics     2200 Cph. N   
 (*) \(*) -- University of Copenhagen   Denmark      Ph: (+45) 35327918
~~~~~~~~~~ - (p.dalgaard@biostat.ku.dk)             FAX: (+45) 35327907
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._