我遇到了与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中使用更多更大的向量/矩阵而没有任何问题。
我显然在这里错过了一些非常愚蠢的东西。我的代码出了什么问题?
答案 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;
(或使用向量,如另一个答案所示)。