protect
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