5

I have the following C++ code :

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);
}

I run it with Rcpp package : sourceCpp("..."). It works well if z1.size() is under 500. But for higher sizes, it crashes and closes R before the second "toto" is printed.

I would like to know :

  • Am I doing something wrong here ?
  • Or is this issue of size in Rcpp known ?
  • Is there a solution to make my code run with z1.size() >0 ?

Thank you !

Pop
  • 12,135
  • 5
  • 55
  • 68

3 Answers3

11

It is even worse than Matthew says as

 double bb[N][N];

is simply wrong as C / C++ have no native two-dimensional structure. You always create a long vector and then use clever indexing into it, see e.g. the old Numerical Recipes in C code for emulating matrices.

Here, this is plain silly as we do have matrix types, so use one:

 Rcpp::NumericMatrix bb(N,N);

The bigger isue that with modern C++, as well as the classes provided by Rcpp, you should never have to use malloc/free or new/delete.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • 2
    +1 for never using `malloc`/`free` or `new`/`delete` (except in resource handles themselves). – Matthew Lundberg Jan 30 '14 at 14:46
  • Is there any documentation on why `malloc`/`free` or `new`/`delete` are not needed in Rcpp? I ask because I have a memory leak in an Rcpp function that only uses Rcpp-classes and I'm trying to track it down and fix it. – alexwhitworth Nov 25 '15 at 17:25
  • Yes, the [Writing R Extensions](https://cran.r-project.org/doc/manuals/r-release/R-exts.html) manual that comes with every copy of R. In particular it stresses that for objects managed by R and returnd you need to allocate from it pool. For you own code you can do whatever you want ... and then fix your own bugs :) My meta-point is that the STL constructs like `std::vector` give you the ability to code without having to managed memory as in the old C days. – Dirk Eddelbuettel Nov 25 '15 at 18:32
8

Despite what others have said, multi dimensional arrays are perfectly valid. However, specifying the dimensions at runtime is only supported in C99. Compilers choose to honour that, but it is not standard. Here is what I get with clang and the -pedantic option:

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.

Community
  • 1
  • 1
Romain Francois
  • 17,432
  • 3
  • 51
  • 77
  • 2
    In fact, this "feature" of C99 was deliberately not adopted by C++. See section 1.2.3 of *The C++ Programming Language, 4th edition*. Stroustrup calls it a "misfeature." – Matthew Lundberg Jan 30 '14 at 16:42
  • Sure. And I agree and look forward for dynarray, etc .. but it is the runtime dimensions that are not standard. multi dim arrays with compile time constant dimensions are perfectly fine, and as you said in your answer, what happened is likely to be stack problems – Romain Francois Jan 30 '14 at 18:19
4

Your problem is in this line:

double bb[N][N];

That is allocating a large number of elements on the stack, and you're running out of stack space. Allocate on the heap instead.

If possible, I would use a std::vector<std::vector<double>> for this. That is a resource handle that allocates its memory on the heap. You don't indicate what you're doing with bb, so I can't tell whether it is possible.

Related: https://stackoverflow.com/a/16411448/1290634

Community
  • 1
  • 1
Matthew Lundberg
  • 42,009
  • 6
  • 90
  • 112