From khansen at stat.Berkeley.EDU  Wed May 24 07:21:38 2006
From: khansen at stat.Berkeley.EDU (Kasper Daniel Hansen)
Date: Tue, 23 May 2006 22:21:38 -0700
Subject: [Rd] protect
In-Reply-To: <Pine.LNX.4.64.0605240458050.6058@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>
	<Pine.LNX.4.64.0605230852590.23195@gannet.stats.ox.ac.uk>
	<41698F04-2224-457D-8A9A-9613A7A03F84@stat.Berkeley.EDU>
	<Pine.LNX.4.64.0605240458050.6058@gannet.stats.ox.ac.uk>
Message-ID: <365EF47A-A95F-4054-9F15-31F4E2CC34D9@stat.Berkeley.EDU>

Thank you very much, that was very helpful. Now I think I understand  
(parts of) the protection mechanism.

/Kasper

On May 23, 2006, at 9:03 PM, Prof Brian Ripley wrote:

> On Tue, 23 May 2006, Kasper Daniel Hansen wrote:
>
>> 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?
>
> That is indeed standard.  The issue is rather that if say foo()  
> extracts an element of a list which has an R-level name, you know  
> that it is already protected.
>
>>>>> 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?
>
> If test() iself does not use anthing from R (that it is C++ is  
> enough of the story), then you do not need to protect it.  Or as in  
> the platform.c example, if it is a constant.  Sorry, the caveats  
> were not clear to me, and I tend not to rely on them as people do  
> sometimes change functions.
>
>> I have tried running my original suggestion with gctorture(TRUE)  
>> and it did not give any errors. But neither did the second  
>> suggested correction.
>
>
> -- 
> 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
Kasper Daniel Hansen