R VECSXP中的保护元件

R VECSXP中的保护元件,r,R,在“编写R扩展”手册中,它说 Protecting an R object automatically protects all the R objects pointed to in the corresponding SEXPREC, for example all elements of a protected list are automatically protected. 这是否意味着我不需要保护VECSXP的单个SEXP元素。例如,考虑下面包含两种方法,我希望在这里说明我需要澄

在“编写R扩展”手册中,它说

Protecting an R object automatically protects all the R objects pointed to in the
corresponding SEXPREC, for example all elements of a protected list are automatically 
protected.
这是否意味着我不需要保护
VECSXP
的单个
SEXP
元素。例如,考虑下面包含两种方法,我希望在这里说明我需要澄清:

#include <Rinternals.h>
#include <R.h>

SEXP copy_int_vec(int *x, int size) {
    SEXP ans = allocVector(INTSXP, size);
    PROTECT(ans);
    int *pans = INTEGER(ans);
    for (int i = 0; i < size; i ++) {
        pans[i] = x[i];
    }
    UNPROTECT(1);
    return ans;
}

// method 1 - protect VECSXP when allocated BUT NOT individual array entries
SEXP method_one() {
    // setup for rep example
    int N = 3;
    int *graph[N];
    int tmp1[3] = {1, 2, 3};
    int tmp2[4] = {1, 2, 3, 4};
    int tmp3[2] = {3, 4};
    graph[0] = tmp1;
    graph[1] = tmp2;
    graph[2] = tmp3;
    int neighbours[3] = {3, 4, 2};

    // method
    SEXP ans = allocVector(VECSXP, N);
    PROTECT(ans);
    for (int i = 0; i < N; i++){
        SET_VECTOR_ELT(ans, i, copy_int_vec(graph[i], neighbours[i]));
    }
    UNPROTECT(1);
    return ans;
}


// method 2 - protect VECSXP when allocated AND ALSO individual array entries
SEXP method_two() {
    // setup for rep example
    int N = 3;
    int *graph[N];
    int tmp1[3] = {1, 2, 3};
    int tmp2[4] = {1, 2, 3, 4};
    int tmp3[2] = {3, 4};
    graph[0] = tmp1;
    graph[1] = tmp2;
    graph[2] = tmp3;
    int neighbours[3] = {3, 4, 2};

    // method 2
    SEXP ans = allocVector(VECSXP, N);
    PROTECT(ans);
    for (int i = 0; i < N; i++){
        SEXP tmp = copy_int_vec(graph[i], neighbours[i]);
        PROTECT(tmp);
        SET_VECTOR_ELT(ans, i, tmp);
    }
    UNPROTECT(N + 1);
    return ans;
}
#包括
#包括
SEXP复制(整数*x,整数大小){
SEXP ans=allocVector(INTSXP,大小);
保护(ans);
int*pans=整数(ans);
对于(int i=0;i

我希望答案是第一种方法,但希望能得到澄清。

我相信
方法之一
可以

要进行分析,您需要知道代码中执行分配的每一点,因为分配可能会触发垃圾收集,这将释放任何未受保护的对象

因此,通过
方法\u one

SEXP method_one() {
    // setup for rep example
    int N = 3;
    int *graph[N];
    int tmp1[3] = {1, 2, 3};
    int tmp2[4] = {1, 2, 3, 4};
    int tmp3[2] = {3, 4};
    graph[0] = tmp1;
    graph[1] = tmp2;
    graph[2] = tmp3;
    int neighbours[3] = {3, 4, 2};
上面的代码都没有使用R的分配器;这些分配都在C堆栈上,因此它们是安全的

    // method
    SEXP ans = allocVector(VECSXP, N);
    PROTECT(ans);
这将执行R分配,然后立即保护它。写这篇文章更常见的方法是

SEXP ans;
PROTECT(ans = allocVector(VECSXP, N));
这使得在分配和保护之间插入语句更难把事情搞砸

    for (int i = 0; i < N; i++){
        SET_VECTOR_ELT(ans, i, copy_int_vec(graph[i], neighbours[i]));
    }
现在什么都没有得到保护;记住不要在返回之前插入任何代码

    return ans;
}
    return ans;
}