From ripley at stats.ox.ac.uk  Tue May 23 09:55:42 2006
From: ripley at stats.ox.ac.uk (Prof Brian Ripley)
Date: Tue, 23 May 2006 08:55:42 +0100 (BST)
Subject: [Rd] protect
In-Reply-To: <Pine.LNX.4.64.0605230814250.17904@gannet.stats.ox.ac.uk>
References: <35168A7B-DFA1-42F7-8763-7769B449005B@stat.berkeley.edu>
	<Pine.LNX.4.64.0605230814250.17904@gannet.stats.ox.ac.uk>
Message-ID: <Pine.LNX.4.64.0605230852590.23195@gannet.stats.ox.ac.uk>

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



[Rd] protect
Prof Brian Ripley