我正在使用.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