Rcpp代码导致R崩溃

5

我有以下的C++代码:

NumericVector testFromontcpp(NumericMatrix z1, NumericMatrix z2, int Nbootstrap){
  int dim1 = z1.nrow();
  int dim2 = z2.nrow();
  int dimension = z1.ncol();
  int N = dim1 + dim2;
  NumericVector TKeps(Nbootstrap+1);
  cout << "toto";
  double bb[N][N];
  cout << "toto";
  return(TKeps);
}

我使用Rcpp包运行它:sourceCpp("...")。如果z1.size()小于500,它可以正常工作。但是对于更大的尺寸,它会崩溃并在第二个“toto”打印之前关闭R。
我想知道:
  • 我在这里做错了什么吗?
  • 还是Rcpp中大小的问题已知?
  • 是否有解决方案使我的代码在z1.size() >0时运行?
谢谢!

是的,正如Matthew告诉你的那样,你的代码是不正确的。我现在添加了一个比他的vector<vector<double>>更好的解决方案。 - Dirk Eddelbuettel
3个回答

11

它甚至比马修说的更糟糕。

 double bb[N][N];

如果说C/C++没有本地的二维结构,那么它就是错误的。你总是要创建一个长向量,然后使用巧妙的索引来模拟矩阵,例如可以看一下旧版本的Numerical Recipes in C。

但现在我们有了矩阵类型,所以使用它就可以了,这种观点非常愚蠢:

 Rcpp::NumericMatrix bb(N,N);

使用现代C++以及Rcpp提供的类,更大的问题是你永远不应该使用malloc/free或者new/delete


2
+1,永远不要使用malloc/freenew/delete(除了在资源句柄本身中使用)。 - Matthew Lundberg
是否有关于为什么在Rcpp中不需要malloc/freenew/delete的文档?我问这个问题是因为我在一个只使用Rcpp类的Rcpp函数中有一个内存泄漏,我正在尝试追踪并修复它。 - alexwhitworth
是的,编写 R 扩展手册随每个 R 版本一同发布。特别强调了对于由 R 管理并返回的对象,需要从其池中分配内存。对于自己的代码,可以随意操作...然后修复自己的错误 :) 我想表达的是,STL 构造如 std::vector 让你能够在不必像旧 C 语言时代那样管理内存的情况下编写代码。 - Dirk Eddelbuettel

8

尽管其他人说过,多维数组是完全有效的。然而,在运行时指定维度仅受 C99 支持。编译器选择遵守它,但这不是标准。这是我使用 clang 和 -pedantic 选项所得到的结果:

array.cpp:13:15: warning: variable length arrays are a C99 feature [-Wvla-extension]
  double bb[N][N];
              ^
array.cpp:13:12: warning: variable length arrays are a C99 feature [-Wvla-extension]
  double bb[N][N];
       ^

See also this question which is related.


2
事实上,C99的这个“特性”被C++故意不采用。请参见《C++程序设计语言》第4版1.2.3节。Stroustrup称其为“不良特性”。 - Matthew Lundberg
当然。我同意并期待dynarray等等...但是运行时维度不是标准。具有编译时常量维度的多维数组完全没问题,正如你在回答中所说,发生的问题很可能是堆栈问题。 - Romain Francois

4

您的问题出现在这一行:

double bb[N][N];

那是在堆栈上分配大量元素,导致堆栈空间不足。请改为在堆上分配。
如果可能的话,我会使用 std::vector<std::vector<double>>。这是一个在堆上分配内存的资源句柄。你没有说明你正在处理什么 bb,所以我无法确定是否可行。
相关链接:https://dev59.com/LXHYa4cB1Zd3GeqPQM8H#16411448

2
为什么?如果需要矩阵,请使用以下代码:Rcpp::NumericMatrix bb(N,N); - Dirk Eddelbuettel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接