Skip to content
Prev 12520 / 63461 Next

Segfault: .Call and classes with logical slots

On 27 Apr 2004, Douglas Bates wrote:

            
It can't be--it only forces gc in places that _could_ result in a gc
withut gctorture; it will not result in a gc in places that otherwise
could not.  The result may be a gc in places that otherwise would be
very unlikely to cause one but not in places that could not.
There are two different scenarios.  Some things are guaranteed not to
allocate, for example low level operations like SET_VECTOR_ELT.
Others, like setAttrib do allocate, but when they do they protect
(some of) their arguments.  So code that uses setAttrib does not need
to protect the arguments to the call (at least the value one--I'd have
to double check the others).  Other variables that are alive before
and after the setAttrib call will need to be protected.

Since slots are stored in attributes we can at most hope for the
second behavior.  But we do not have it.  SET_SLOT is a macro that
expands to R_do_slot_assign, which starts out as

SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) {
    SEXP input = name; int nprotect = 0;
    if(isSymbol(name) ) {
	input = PROTECT(allocVector(STRSXP, 1)); nprotect++; /******/
	SET_STRING_ELT(input, 0, PRINTNAME(name));
    }
    else if(!(isString(name) && LENGTH(name) == 1))
	error("invalid type or length for slot name");
    ...

The actual assignment uses setAttrib, which does operate in a way that
protects the value being assigned, but the unprotected allocation at
/******/ happens before we get there.

So unless we modify SET_SLOT to protect the value argument (and the
others as well to be safe), the value needs to be protected (as do any
other objects that might be needed after the call).

Best,

luke