Rcpp:数组上的段错误 > 698152 如果声明了整数向量

Rcpp: segfault on arrays > 698152 if IntegerVector is declared

本文关键字:698152 gt 如果 声明 向量 整数 数组 段错误 错误 Rcpp      更新时间:2023-10-16

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

测试。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的数组(不管它们是整型还是双精度,它们都会以同样的方式崩溃),实例化一个大小为10的IntegerVector,并填充数组的前两个位置。我可以删除这里的任何一行,它不会崩溃。它也不会与N <698153(这个临界数字因机器而异……500,000似乎总是安全的,而1e6到处都是崩溃)。如果我只迭代到j <2而不是j <N,即当它尝试填充数组的第二个位置时。>

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

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

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/

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

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

(或者使用vector,正如另一个答案中建议的那样)。