[Rd] protect

Kasper Daniel Hansen khansen at stat.Berkeley.EDU
Wed May 24 02:15:36 CEST 2006


Thank you very much. I think I do have a clearer understanding, but I  
have a few questions

On May 23, 2006, at 12:55 AM, Prof Brian Ripley wrote:

> On Tue, 23 May 2006, Prof Brian Ripley wrote:
>
>> On Mon, 22 May 2006, Kasper Daniel Hansen wrote:
>>
>>> I have a few simple questions about the usage of PROTECT, more
>>> specifically how careful one needs to be. Simple yes/no answers are
>>> fine.
>>
>> (Except that in the last case they would be misleading.)
>>
>>> Most of the uses I have seen do protection when memory is allocated.
>>> But what if one just want to assign a value of another function to a
>>> variable. Say eg. that foo is a function that returns a SEXP. Would
>>> the following code be fine?
>>>
>>> SEXP bar;
>>> PROTECT(bar = foo());
>>
>> It would be fine but may be unnecessary.  It is objects and not  
>> pointers
>> which are protected, and a SEXP is a pointer.  So protection is  
>> needed
>> only if foo() might return a pointer to an unprotected object.

Ok. I have been coding foo in such a way that I unprotect everything  
in foo just before returning its value. I thought that was the  
"standard" way to do - is that true? Or should I leave the return  
value protected and then unprotect in the function calling foo?

>>> Also, basically in one use case I would want to return the value of
>>> foo immediately, but I need to do some cleaning up first, which has
>>> nothing to do with R (more specifically, I need to close various
>>> files). Would I then need to protect foo, as in
>>>
>>> SEXP bar;
>>> bar = foo();
>>> "close the file in C++"
>>> return bar;
>>
>> Fine, as PROTECT protects against R garbage collection, and that  
>> can only
>> happen if R's functions are called.
>>
>>> Finally, I am also assigning values to the components of a list.
>>> Would the following be ok
>>>
>>> SEXP bar;
>>> PROTECT(bar = NEW_LIST(2));
>>> SET_VECTOR_ELT(bar, 0, ScalarInteger(test());
>>>
>>> (where test is a function returning int, which again has nothing to
>>> do with R - it interfaces to an extern library), or do I need to
>>> hedge myself against garbage collection in the SET_VECTOR_ELT macro?
>>
>> You do need to protect but elsewhere in this call, as  
>> ScalarInteger does
>> memory allocation:
>>
>> INLINE_FUN SEXP ScalarInteger(int x)
>> {
>>     SEXP ans = allocVector(INTSXP, 1);
>>     INTEGER(ans)[0] = x;
>>     return ans;
>> }
>>
>> but SET_VECTOR_ELT does not.  So you need
>>
>> SEXP bar, tmp;
>> PROTECT(bar = NEW_LIST(2));
>> PROTECT(tmp = test());
>> SET_VECTOR_ELT(bar, 0, ScalarInteger(tmp));
>> UNPROTECT(1);
>
> Or a design that uses fewer PROTECTs
>
> SEXP bar, tmp;
> PROTECT(bar = allocVector(VECSXP, 2));
> tmp = allocVector(INTSXP, 1);
> SET_VECTOR_ELT(bar, 0, tmp);
> INTEGER(tmp)[0] = test();

I thought I got this. Then I grepped the sources and found this in  
main/platform.c:

     PROTECT(ans = allocVector(VECSXP, 18));
     PROTECT(nms = allocVector(STRSXP, 18));
     SET_STRING_ELT(nms, 0, mkChar("double.eps"));
     SET_VECTOR_ELT(ans, 0, ScalarReal(R_AccuracyInfo.eps));

This looks very similar to what I did above. In my case "test" was a C 
++ function coming from outside of R returning an int. That was  
perhaps not clear from my original mail, since the first suggested  
correction had
PROTECT(tmp = test());
indicating that the return value for test is a SEXP. Or am I  
completely of?

I have tried running my original suggestion with gctorture(TRUE) and  
it did not give any errors. But neither did the second suggested  
correction.

Thanks, Kasper


> -- 
> Brian D. Ripley,                  ripley at stats.ox.ac.uk
> Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
> University of Oxford,             Tel:  +44 1865 272861 (self)
> 1 South Parks Road,                     +44 1865 272866 (PA)
> Oxford OX1 3TG, UK                Fax:  +44 1865 272595



More information about the R-devel mailing list