Bro*_*ieG 6 c garbage-collection r
我认为这是非常简单的,基本上,任何SEXP我创建类型对象的C代码必须受到保护,但它开始使用链表何时开始有点迷雾(对我)CAR/ CDR等我开始了与在此评论如何写R扩展:
保护R对象会自动保护相应SEXPREC中指向的所有R对象,例如受保护列表的所有元素都会自动受到保护.
这来自R Internals:
SEXPREC是一个C结构,包含如上所述的32位头,三个指针(属性,前一个和下一个节点)和节点数据......
LISTSXP:指向CAR,CDR(通常为LISTSXP或NULL)和TAG(SYMSXP或NULL)的指针.
所以我认为这意味着,如果我这样做:
SEXP s, t, u;
PROTECT(s = allocList(2));
SETCAR(s, ScalarLogical(1));
SETCADR(s, ScalarLogical(0));
t = CAR(s);
u = CADR(s);
Run Code Online (Sandbox Code Playgroud)
然后t,u并通过指向受保护列表中的对象来保护s(推论问题:有没有办法获得对象的PROTECTED状态?在Rinternals.h中看不到符合条件的任何内容).但我看到像(来自src/main/unique.c)的东西:
// Starting on line 1274 (R 3.0.2), note `args` protected by virtue of being
// a function argument
SEXP attribute_hidden do_matchcall(SEXP call, SEXP op, SEXP args, SEXP env)
{
// ommitting a bunch of lines, and then, on line 1347:
PROTECT(b = CAR(args));
// ...
}
Run Code Online (Sandbox Code Playgroud)
这表明其中的所有对象args都没有受到保护,但这似乎很奇怪,因为任何args对象都可以在任何时候获得GCed.由于CAR只返回指向可能已经受保护的对象的指针,为什么我们需要在这里保护它?
这样想:实际上PROTECT并没有对对象做任何事情。相反,它添加一个临时 GC 根,以便收集器认为该对象还活着。它包含的任何对象也是活动的,不是因为 C 应用了某种保护,而是因为它们被另一个本身已被视为活动的对象所指向-与任何其他正常的活动对象相同。因此,设置受保护列表的汽车不仅使该对象保持活动状态,还可能释放汽车中先前存在的所有内容以进行 GC,将其从特定的活动树中删除(保护列表不会递归地影响元素)。
因此,一般来说,您不会有一种简单的方法来判断一个对象在更广泛的意义上是否受到“保护”,因为它实际上只是遵循与 GC 在其他地方所做的相同规则,并且该对象没有什么特别的。您可以跟踪整个列表并查看是否找到它,但这会......至少可以说效率低下(也没有什么可说的,从列表PROTECT中的对象到有问题的对象的所有权树PROTECT是能够使其存活时间最长的一个)。
in 中的行do_matchcall实际上是出于完全不相关的原因而存在的:保护CAR(args)仅发生在条件的一个分支中 - 在另一个分支中,它是一个新创建的受到保护的对象。冗余地保护该分支的值也意味着无论采用哪个分支,堆栈上都保证有相同数量的对象PROTECT,这将函数UNPROTECT末尾的对应简化为对恒定数量的槽的操作(无需复制检查来改变它)。