NiceStats NiceStats - 2 months ago 28
R Question

NumericMatrix: why can I index beyond its dimensions without error?

I have R code which passes a matrix() object into an Rcpp function whose parameter is NumericMatrix. The C++ function gives the correct dimensions, but I can also index the NumericMatrix beyond its dimensions without error. Why does this happen? MWE below (a .cpp file created in RStudio) followed by one instance of the output I see, where the third line is obviously(?) reading from memory outside the bounds of the array.

#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
void myFn(Rcpp::NumericMatrix X) {
std::cout << X.nrow() << std::endl;
std::cout << X.ncol() << std::endl;

std::cout << X(100,4) << std::endl;
}

/*** R
# create a matrix to be passed to the C++ function
mat = matrix(3, nrow=10, ncol=3)
myFn(mat)
*/

# 10
# 3
# 3.96421e+252

Answer

Couple of quick ones:

  1. Your code includes the RcppArmadillo header and sets a depends, but does not use RcppArmadillo. Not good practice (though not harmful).

  2. You use std::cout which CRAN and WRE both frown upon.

  3. Use the .at(i,j) accessor if you want bounds control; this is off by default for performance reasons.

Modified example below.

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
void myFn(Rcpp::NumericMatrix X) {
  Rcout << X.nrow() << " " << X.ncol() << std::endl;
  Rcout << X.at(100,4) << std::endl;
}

/*** R
# create a matrix to be passed to the C++ function
mat = matrix(3, nrow=10, ncol=3)
myFn(mat)
*/

If you run that you get error you desire:

R> Rcpp::sourceCpp("/tmp/indexExample.cpp")

R> # create a matrix to be passed to the C++ function
R> mat = matrix(3, nrow=10, ncol=3)

R> myFn(mat)
10 3
Error in eval(substitute(expr), envir, enclos) (from srcConn#3) : index out of bounds
R>