1

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

测试.R:

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

测试.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 < 698153 时崩溃(这个关键数字因机器而异...... 500000 似乎总是安全的,而 1e6 到处崩溃)。如果我只迭代直到 j < 2 而不是 j < N,它就会崩溃,即当它尝试填充数组的第二个位置时。

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

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

4

2 回答 2

10
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/

于 2013-06-14T09:45:14.737 回答
6

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

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

... 

delete [] closestLandmarks;
delete [] closestLandmarksIdx; 

(或使用向量,如另一个答案中所建议的那样)。

于 2013-06-14T09:46:55.223 回答