On Sep 15, 2012, at 10:50 PM, Simon Knapp wrote: > OK I think I'm getting it, but one more question if I may... > > When I write a function, I don't protect the arguments explicitly (I > understand that they should be protected within the calling function) - are > my functions examples of functions that "protect their arguments"?
The way I understand your question, no. > Looking at the code for setAttrib, which does explicitly protect its first > two arguments (why not the third??? That's actually a good question :) - for the case of TYPEOF(name) == SYMSXP it doesn't need to because there is no allocation in the path until val is used, but for TYPEOF(name) == STRSXP there is a potential allocation in the handling of name. That could very well be a bug ... > ), I'd presume the answer is no and hence that I should protect new SEXPs > before > passing them to such functions. > Yes. Note that PROTECT has a fairly low cost so if in doubt, it's better to over-protect. Cheers, Simon > Yet more thanks :-) > Simon > > > > On Sun, Sep 16, 2012 at 5:08 AM, Simon Urbanek > <simon.urba...@r-project.org> wrote: >> >> On Sep 15, 2012, at 2:57 PM, Simon Urbanek wrote: >> >>> >>> On Sep 15, 2012, at 11:28 AM, Simon Knapp wrote: >>> >>>> Hi Simon, >>>> >>>> Thanks for your advice, but I'm still not clear. In my case I don't >>>> want to modify the result - the integer acts as a handle for indexing >>>> an array in later calls back into my library. >>>> >>>> As I understand it, returning result like >>>> >>>> SEXP func(SEXP arg) {return arg;} >>>> >>>> would not copy arg and hence I would have two pointers to the same >>>> object immediately after the call... and (if this is the case) I'm not >>>> sure whether this is OK. >>>> >>> >>> My answer is was, yes, it's ok. >>> >>> >>>> Just to be clear, are you saying that the proper way to do things is >>>> (at the end of my function in the original post): >>>> >>>> SET_SLOT(ans, Rf_install("myInteger"), duplicate(thingysInteger)); >>>> return ans; >>>> >>>> rather than >>>> >>>> SET_SLOT(ans, Rf_install("myInteger"), thingysInteger); >>>> return ans; >>>> >>>> ? >>>> >>> >>> No, because you're not modifying anything in that case. >>> >>> >>>> The last thing I'm not clear on is if it is OK to create a new SEXP >>>> (with a call like duplicate) in a call to another function (as in the >>>> first case above) or does this leave it unprotected? >>>> >>> >>> Most functions (but not all - a notable exception is eval) protect their >>> arguments, so it's ok in most cases. But this is no different than any >>> other SEXP result - not specific to duplicate() in particular. >>> >> >> Actually, I should explain a bit, because the above case is not about >> SET_SLOT protecting or not protecting arguments. In fact it does protect its >> arguments, but even when you are calling a function that protects its >> arguments, you can get into trouble. But let's take a more common example >> (since you really don't want to call duplicate() in your example) - let's >> say you want to do something like >> >> setAttrib(foo, install("bar"), mkString("bar")); >> >> Although setAttrib() is friendly an protects its arguments, the above is >> bad, because the mkString() is unprotected while install() is called. Now, >> symbols don't need protection, but it is possible that install() will >> trigger allocation, so the mkString() result is in danger. The best way >> around is something like >> >> SEXP bar = install("bar") >> setAttrib(foo, bar, mkString("bar")); >> >> Here mkString() is fine, because there cannot be an allocation before >> setAttrib() protects its arguments. Also bar is a symbol so it doesn't need >> to be protected, so the above is ok. > > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel