Rcpp:关于数组的段错误> 698152如果声明了IntegerVector

时间:2013-06-14 09:40:57

标签: c++ r segmentation-fault rcpp

我遇到了与Rcpp接口的c ++代码可能存在的内存问题。我可以提出以下最小测试用例:

test.R:

require(Rcpp)
sourceCpp("test.cpp")
N <- 698153
testCpp(N)

TEST.CPP:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]] 
void testCpp(int N) {
    double closestLandmarks[N];
    int closestLandmarksIdx[N];
    IntegerVector l(10);
    // Fill the double and int vectors
    for (int j = 0; j < N; j++) {
        closestLandmarks[j] = 1;
        closestLandmarksIdx[j] = 2;
    } // j

    return;
}

运行Rscript test.R会导致堆栈溢出:Error: segfault from C stack overflow。基本上,这段代码分配了两个大小为N的数组(如果它们是int或double则无关紧要,它们会以相同的方式崩溃),实现大小为10的IntegerVector,并填充数组的前2个位置。我基本上可以在这里删除任何一行,它不会崩溃。它也不会因N&lt; 698153(这个关键数字在机器之间有所不同...... 500000似乎总是安全的,而1e6在任何地方都崩溃了)。如果我只迭代直到j&lt; 2代替j&lt; N,即它尝试填充数组的第二个位置时。

我不明白为什么我应该遇到2个数组的内存问题我认为相当小(&lt; 106)和非常小的IntegerVector。我的机器有足够的可用内存(24GB中有5GB)我可以在R中使用更多更大的向量/矩阵而没有任何问题。

我显然在这里错过了一些非常愚蠢的东西。我的代码出了什么问题?

2 个答案:

答案 0 :(得分:9)

double closestLandmarks[N];
int closestLandmarksIdx[N];

都被分配到堆栈中。对于大N,堆栈将溢出,这意味着堆栈上的空间很小。

您可以在堆上分配对象。 std::vector会为您做到这一点。 我建议:

std::vector<double> closestLandmarks(N);
std::vector<int> closestLandmarksIdx(N);

这是一个有趣的阅读链接,教你堆栈和堆栈之间的区别: http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/

答案 1 :(得分:6)

您的堆栈空间不足。堆栈只有很多内存(存储局部变量的地方)。您需要使用动态分配:

double *closestLandmarks = new double[N];
int *closestLandmarksIdx = new int[N];

... 

delete [] closestLandmarks;
delete [] closestLandmarksIdx; 

(或使用向量,如另一个答案所示)。