[Rcpp-devel] Loading a package using Rcpp Modules results in memory corruption
Dirk Eddelbuettel
edd at debian.org
Sun Jan 9 19:07:53 CET 2011
On 9 January 2011 at 12:12, Dominick Samperi wrote:
| Actually, the problem seems to be pretty transparent, and the
| solution is the same (see below). This gets you through Evaluator,
| but you fail in SlotProxy in the call to "$<-". The fact that these
| problems only appear when gctorture() is turned on suggests
| that they all of the same explanation: unprotected SEXP's.
|
| same:
| //#define UNSAFE_CODE
| #ifdef UNSAFE_CODE
| int error = LOGICAL( Rf_eval( Rf_lang1( Rf_install("errorOccured") ),
| RCPP ) )[0];
| #else
| SEXP cmd = PROTECT(Rf_lang1( Rf_install("errorOccured")));
| int error = LOGICAL(Rf_eval( cmd, RCPP ))[0];
| UNPROTECT(1);
| #endif
| Rprintf("Got error = %d\n", error);
|
There may be an impedance mismatch going on. 'Writing R Extension' says
4.3.1 Using gctorture
---------------------
We can help to detect memory problems earlier by running garbage
collection as often as possible. This is achieved by
`gctorture(TRUE)', which as described on its help page
Provokes garbage collection on (nearly) every memory allocation.
Intended to ferret out memory protection bugs. Also makes R run
_very_ slowly, unfortunately.
The reference to `memory protection' is to missing C-level calls to
`PROTECT'/`UNPROTECT' (*note Garbage Collection::) which if missing
allow R objects to be garbage-collected when they are still in use.
But it can also help with other memory-related errors.
Normally running under `gctorture(TRUE)' will just produce a crash
earlier in the R program, hopefully close to the actual cause. See the
next section for how to decipher such crashes.
It is possible to run all the examples, tests and vignettes covered
by `R CMD check' under `gctorture(TRUE)' by using the option
`--use-gct'.
I do not see this as compatible with the C++ Design principle we use whereby
protection / unprotection occurs relative to the end of scope -- and not
after every single assignment or allocation.
In other words, gctorture() may well be a fine test for the C API and its
PROTECT and UNPROTECT at every step but possibly not quite as much for Rcpp.
Dirk
PS Here is slight generalization of your examples. Cases 2 and 3 do not bomb,
and Case 3 is using almost all Rcpp idioms (but for the final Rf_eval call).
-----------------------------------------------------------------------------
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
#include "Rcpp.h"
RcppExport SEXP testfft(SEXP vec, SEXP env, SEXP choiceS) {
int choice = Rcpp::as<int>(choiceS);
SEXP res = R_NilValue;
if (choice == 1) {
Rprintf("In case 1\n");
// may not survive gctorture(), sometimes!
SEXP call = ::Rf_lcons(Rf_install("fft"),
Rf_cons(vec , R_NilValue));
res = PROTECT(Rf_eval(call, env));
UNPROTECT(1);
} else if (choice == 2) {
Rprintf("In case 2\n");
// always survives gctorture()
SEXP call = PROTECT(::Rf_lcons(Rf_install("fft"),
Rf_cons(vec , R_NilValue)));
res = PROTECT(Rf_eval(call, env));
UNPROTECT(2);
} else if (choice == 3) {
Rprintf("In case 3\n");
Rcpp::Function fft("fft");
Rcpp::Environment env_(env);
Rcpp::Language call(fft);
call.push_back(vec);
res = Rf_eval(call, env_);
}
return res;
}
-----------------------------------------------------------------------------
and
-----------------------------------------------------------------------------
# Tests Rcpp Evaluator code with PROTECTION fix and gctorture ON.
# Should get a complex vector of zeros.
library(Rcpp)
gctorture()
dyn.load("testfft.so")
for (i in 2:3) { # bombs on 1 but not 2 or 3
print(.Call('testfft', 1:20, getNamespace("stats"), i) - fft(1:20))
}
cat("still here\n")
-----------------------------------------------------------------------------
edd at max:/tmp/samperi-gc$ r -lRcpp -e'Rcpp:::SHLIB("testfft.cpp")'
ccache g++ -I/usr/share/R/include -I/usr/local/lib/R/site-library/Rcpp/include -fpic -g -O3 -Wall -pipe -pedantic -Wno-variadic-macros -c testfft.cpp -o testfft.o
g++ -shared -o testfft.so testfft.o -L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib -L/usr/lib64/R/lib -lR
edd at max:/tmp/samperi-gc$ r torture.R
Loading required package: methods
In case 2
[1] 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i
In case 3
[1] 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i
still here
edd at max:/tmp/samperi-gc$
--
Dirk Eddelbuettel | edd at debian.org | http://dirk.eddelbuettel.com
More information about the Rcpp-devel
mailing list