Ben, Thanks SO much for the work you did to discover this problem. I've committed a fix in rev 4319 (also bumped the version to 0.10.3.3 so a new tarball will also be available from R-forge soon).
Best, J.J. On Fri, May 17, 2013 at 8:12 AM, QRD <q...@sig.com> wrote: > Hi, > > On Thu, May 16, 2013 at 11:02 AM, Dirk Eddelbuettel <e...@debian.org> > wrote: > > Here is the self-contained example I asked for. > > > > And yes, it crashes for me too. So let's not create 1e6 temp matrices. > > Until someone has time to debug memory management internals. Which is > > really hard, so this may not get fixed for a while. Sorry. > > > > #!/usr/bin/Rscript > > > > library(Rcpp) > > myFun <- cppFunction('NumericMatrix myFun(NumericMatrix input, int n){ > > NumericMatrix A(n, n); > > for(int Row = 0; Row < n; Row++) { > > for(int Col = 0; Col < n; Col++) { > > A(Row, Col) = input(Row, Col); > > } > > } > > return A; > > }') > > > > n <- 10 > > x <- 1:n^2 > > N <- 1e6 > > b <- 0 > > for (j in 1:N) { > > means <- matrix(x, n, n) > > res <- myFun(means, n) > > a <- res[1, 1] > > b <- b + a > > } > > > > cat(sprintf("Done, b is %d\n", b)) > > I had a look at this, and I think I see what's going on. > > The error is reproducible much more quickly under gctorture(), and then > working directly with the generated code in its own C++ file, I was able > to cut it down to: > > - - - - 8< - - - - crash-fn.r > > require(methods) > require(Rcpp) > > dll.info <- dyn.load("crash-fn") > mod <- Module("Crash", dll.info, mustStart = TRUE) > myFun <- mod$myFun > > N <- 25 > b <- 0 > > for (j in 1:N) { > gctorture(TRUE) > res <- myFun() > gctorture(FALSE) > b <- b + res[1] > } > > - - - - 8< - - - - crash-fn.cpp > > #include <Rcpp.h> > > static SEXP myFun() > { > Rcpp::RNGScope __rngScope; > Rcpp::NumericMatrix __result(5, 5); > > return Rcpp::wrap(__result); > } > > RCPP_MODULE(Crash) > { > Rcpp::function("myFun", &myFun); > } > > - - - - 8< - - - - > > Then: > > R CMD SHLIB crash-fn.cpp && Rscript crash-fn.r > > reliably and quickly crashes. > > I think what happens is that the > > return Rcpp::wrap(__result); > > line at the end of the function pulls the m_sexp out of the > NumericMatrix (because a NumericMatrix is an RObject) via > > inline operator SEXP() const { return m_sexp ; } > > and gets ready to return it. But before the 'return' actually happens, > the destructors for the NumericMatrix and the RNGScope get called, in > that order. The NumericMatrix destructor releases its underlying SEXP, > via the base class destructor > > RObject::~RObject() { > RCPP_DEBUG_1("~RObject(<%p>)", m_sexp) > Rcpp_ReleaseObject(m_sexp) ; > } > > and now our return-value SEXP is unprotected. The destructor of > RNGScope then runs, calling PutRNGstate(), where (reliably under > gctorture(); very occasionally without this) our result SEXP gets > re-allocated, or otherwise stomped on. > > If you swap the order of the declarations of __rngScope and __result, > the code runs correctly, supporting this explanation. > > As for a fix, one way would be to wrap an extra scope round the main > body of the generated code and PROTECT the wrapped result. This works > in my cut-down example: > > static SEXP myFun() > { > SEXP __sexp_result; > { > Rcpp::RNGScope __rngScope; > Rcpp::NumericMatrix __result(5, 5); > > PROTECT(__sexp_result = Rcpp::wrap(__result)); > } > UNPROTECT(1); > return __sexp_result; > } > > and the generated code could instead be > > RcppExport SEXP sourceCpp_78413_myFun(SEXP inputSEXP, SEXP nSEXP) { > BEGIN_RCPP > SEXP __sexp_result; > { > Rcpp::RNGScope __rngScope; > NumericMatrix input = Rcpp::as<NumericMatrix >(inputSEXP); > int n = Rcpp::as<int >(nSEXP); > NumericMatrix __result = myFun(input, n); > PROTECT(__sexp_result = Rcpp::wrap(__result)); > } > UNPROTECT(1); > return __sexp_result; > END_RCPP > } > > I'm not fully familiar with how the C++ code gets generated, but perhaps > somebody who is could implement this or similar fix? > > Thanks, > > Ben. > _______________________________________________ > Rcpp-devel mailing list > Rcpp-devel@lists.r-forge.r-project.org > https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel >
_______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel