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

Reply via email to