[Rd] Question about copying arguments in C.

Simon Urbanek simon.urbanek at r-project.org
Sun Sep 16 16:00:38 CEST 2012


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.urbanek at 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.
> 
> 



More information about the R-devel mailing list