Skip to content
Prev 11178 / 12125 Next

[R-pkg-devel] Replacement for SETLENGTH

On 1/15/25 05:26, Merlise Clyde, Ph.D. wrote:
The important part for protection is that Rf_lengthgets _may_ return a 
freshly allocated object. This means that the object needs protection 
from garbage collection, implicit or explicit - and that is covered in 
section "Handling the effects of garbage collection".? There are? many 
functions in the? R API that return freshly allocated objects, so don't 
expect that documentation of every such function would give advice on 
how to protect, that is covered in that special section.

So, you are right, some protection is needed _if_ the return value of 
Rf_lengthgets may be exposed to gc().
You have protected two objects here, one was in x0 and one in x1 
(REPROTECT doesn't change the depth of the protection stack). Some 
people put that into a comment:

UNPROTECT(2); /* x1, x0 */

The code above is ok. In some cases, you can shuffle it around a bit or 
rely on implicit protection if you want to reduce the need for explicit 
protection. But perfomance-wise it doesn't matter given code that is 
allocating, etc, that takes much more time - it is more about readability.

For instance,

result = PROTECT(allocVector(...))
x0 = allocVector()
SET_VECTOR_ELT(result, 0, x0);
// now x0 is implicitly protected via result
...

x0 = Rf_lengthgets(..)
SET_VECTOR_ELT(result, 0, x0);
/// now the new value of x0 is implicitly protected via result (the old 
value may not be)

UNPROTECT(1)? // result
return result
PreserveObject/ReleaseObject is good e.g. for global structures, 
probably not in this case. The difficulty there is making sure 
ReleaseObject() does execute in case of error, a non-local return. On 
the other hand, protection via PROTECT/UNPROTECT is automatically robust 
to non-local returns (automatic unprotection).

There is nothing specific about Rf_lengthgets wrt to protection here - 
the same rules apply to any other R API function that returns an SEXP.

For finding protection bugs in code, one can use an R build with barrier 
checking enabled and gctorture or rchk tool. Some bugs may lead to 
crashes or incorrect outputs even in normaln builds. Some bugs may be 
found by UBSAN. But none of this is a verification tool, one can only 
find some bugs in some cases, correctness remains the responsibility of 
the programmer.

Best
Tomas