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

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);


-- 
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