[Rd] protect
Prof Brian Ripley
ripley at stats.ox.ac.uk
Tue May 23 09:55:42 CEST 2006
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.
>
>> 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();
--
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