[Rcpp-devel] Segfault error during simulation in Rcpp: explanation/fix
JJ Allaire
jj.allaire at gmail.com
Sat May 18 03:51:05 CEST 2013
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 <qrd at sig.com> wrote:
> Hi,
>
> On Thu, May 16, 2013 at 11:02 AM, Dirk Eddelbuettel <edd at 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 at lists.r-forge.r-project.org
> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20130517/a9561808/attachment.html>
More information about the Rcpp-devel
mailing list