C中的R扩展:请参阅SEXP PROTECT堆栈高度



我正在使用.Call接口编写R扩展,并试图跟踪堆栈不平衡警告。如果我能够查阅代码中不同点的堆栈高度,以隔离内部C函数,这些函数不会以调用时的SEXP PROTECT堆栈高度返回,我会发现这非常有帮助。

有办法做到这一点吗?

是的,我意识到如果我使用Rcpp,我就不必担心这些了,但我已经深陷其中,无法改变。

一种不太理想的可能性是这样的模式:

int start, end;
PROTECT_WITH_INDEX(R_NilValue, &start);
UNPROTECT(1);
call_to_suspect_fun();
PROTECT_WITH_INDEX(R_NilValue, &end);
UNPROTECT(1);
if(start != end) error("Stack imbalance right here!");

这看起来非常尴尬。我想它很容易变成一个函数,但如果没有更好的内置选项,我会感到惊讶。

堆栈的顶部不是公共API的一部分,但可以显示

#include "Rinternals.h"
extern int R_PPStackTop;
SEXP stacktop()
{
    SEXP x;
    Rprintf("%dn", R_PPStackTop);
    x = PROTECT(allocVector(INTSXP, 1));
    Rprintf("%dn", R_PPStackTop);
    UNPROTECT(1);
    Rprintf("%dn", R_PPStackTop);
    return Rf_ScalarInteger(R_PPStackTop);
}

导致

$ R CMD SHLIB stacktop.c 2&> /dev/null
$ R --vanilla -e "dyn.load('stacktop.so'); .Call('stacktop')"
> dyn.load('stacktop.so'); .Call('stacktop')
3
4
3
[1] 3

最新更新