I re-read the bit about garbage collection in writing R extensions multiple times now, and still don't understand the difference between these two usages:

SEXP var = PROTECT(allocVector(STRSXP, 100));

vs

SEXP var;
PROTECT(var = allocVector(STRSXP, 100));

So far I've had worse luck with the first one as my session sometimes crashes with it (yet I see that usage a lot in both real code and in the intro guide itself). Can someone please explain the difference between these two assignments?

edit:

After some experimentation I think I'm coming to the conclusion that there is no difference between the above two and any difference in crashing behavior I see is accidental, but would appreciate a confirmation from someone more experienced.

有帮助吗?

解决方案

It is strictly equivalent. This is the function called by PROTECT (from https://svn.r-project.org/R/trunk/src/main/memory.c)

SEXP protect(SEXP s)
{
    if (R_PPStackTop >= R_PPStackSize)
    R_signal_protect_error();
    R_PPStack[R_PPStackTop++] = CHK(s);
    return s;
}

static R_INLINE SEXP CHK(SEXP x)
{
    /* **** NULL check because of R_CurrentExpr */
    if (x != NULL && TYPEOF(x) == FREESXP)
    error("unprotected object (%p) encountered (was %s)",
          x, sexptype2char(OLDTYPE(x)));
    return x;
}
#else
#define CHK(x) x
#endif

and from.include/Rinternals.h:

#define TYPEOF(x)   ((x)->sxpinfo.type)

As you can see, the pointer argument is returned unchanged, so that

var = PROTECT(p)
PROTECT(var = p)

are equivalent

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top