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, [EMAIL PROTECTED] 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 ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel