<br><br><div class="gmail_quote">On Sun, Jan 9, 2011 at 1:07 PM, Dirk Eddelbuettel <span dir="ltr"><<a href="mailto:edd@debian.org">edd@debian.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div class="im"><br>
On 9 January 2011 at 12:12, Dominick Samperi wrote:<br>
| Actually, the problem seems to be pretty transparent, and the<br>
| solution is the same (see below). This gets you through Evaluator,<br>
| but you fail in SlotProxy in the call to "$<-". The fact that these<br>
| problems only appear when gctorture() is turned on suggests<br>
| that they all of the same explanation: unprotected SEXP's.<br>
|<br>
| same:<br>
| //#define UNSAFE_CODE<br>
| #ifdef UNSAFE_CODE<br>
| int error = LOGICAL( Rf_eval( Rf_lang1( Rf_install("errorOccured") ),<br>
| RCPP ) )[0];<br>
| #else<br>
| SEXP cmd = PROTECT(Rf_lang1( Rf_install("errorOccured")));<br>
| int error = LOGICAL(Rf_eval( cmd, RCPP ))[0];<br>
| UNPROTECT(1);<br>
| #endif<br>
| Rprintf("Got error = %d\n", error);<br>
| <br>
<br>
</div>There may be an impedance mismatch going on. 'Writing R Extension' says<br>
<br>
4.3.1 Using gctorture<br>
---------------------<br>
<br>
We can help to detect memory problems earlier by running garbage<br>
collection as often as possible. This is achieved by<br>
`gctorture(TRUE)', which as described on its help page<br>
<br>
Provokes garbage collection on (nearly) every memory allocation.<br>
Intended to ferret out memory protection bugs. Also makes R run<br>
_very_ slowly, unfortunately.<br>
<br>
The reference to `memory protection' is to missing C-level calls to<br>
`PROTECT'/`UNPROTECT' (*note Garbage Collection::) which if missing<br>
allow R objects to be garbage-collected when they are still in use.<br>
But it can also help with other memory-related errors.<br>
<br>
Normally running under `gctorture(TRUE)' will just produce a crash<br>
earlier in the R program, hopefully close to the actual cause. See the<br>
next section for how to decipher such crashes.<br>
<br>
It is possible to run all the examples, tests and vignettes covered<br>
by `R CMD check' under `gctorture(TRUE)' by using the option<br>
`--use-gct'.<br>
<br>
I do not see this as compatible with the C++ Design principle we use whereby<br>
protection / unprotection occurs relative to the end of scope -- and not<br>
after every single assignment or allocation.<br></blockquote><div><br>Thanks, but note that Doug's original report was not about gctorture(). We<br>are using this tool to try to fix the memory corruption problems, and this<br>
tool seems to be pretty helpful for this purpose, even if it might be too<br>demanding in some situations.<br><br>Dominick<br><br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<br>
In other words, gctorture() may well be a fine test for the C API and its<br>
PROTECT and UNPROTECT at every step but possibly not quite as much for Rcpp.<br>
<br>
Dirk<br>
<br>
PS Here is slight generalization of your examples. Cases 2 and 3 do not bomb,<br>
and Case 3 is using almost all Rcpp idioms (but for the final Rf_eval call).<br>
<br>
-----------------------------------------------------------------------------<br>
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-<br>
<br>
#include "Rcpp.h"<br>
<br>
RcppExport SEXP testfft(SEXP vec, SEXP env, SEXP choiceS) {<br>
<br>
int choice = Rcpp::as<int>(choiceS);<br>
SEXP res = R_NilValue;<br>
<br>
if (choice == 1) {<br>
Rprintf("In case 1\n");<br>
// may not survive gctorture(), sometimes!<br>
SEXP call = ::Rf_lcons(Rf_install("fft"),<br>
Rf_cons(vec , R_NilValue));<br>
res = PROTECT(Rf_eval(call, env));<br>
UNPROTECT(1);<br>
<br>
} else if (choice == 2) {<br>
Rprintf("In case 2\n");<br>
// always survives gctorture()<br>
SEXP call = PROTECT(::Rf_lcons(Rf_install("fft"),<br>
Rf_cons(vec , R_NilValue)));<br>
res = PROTECT(Rf_eval(call, env));<br>
UNPROTECT(2);<br>
<br>
} else if (choice == 3) {<br>
Rprintf("In case 3\n");<br>
Rcpp::Function fft("fft");<br>
Rcpp::Environment env_(env);<br>
Rcpp::Language call(fft);<br>
call.push_back(vec);<br>
res = Rf_eval(call, env_);<br>
}<br>
return res;<br>
}<br>
-----------------------------------------------------------------------------<br>
<br>
and<br>
<br>
-----------------------------------------------------------------------------<br>
# Tests Rcpp Evaluator code with PROTECTION fix and gctorture ON.<br>
# Should get a complex vector of zeros.<br>
library(Rcpp)<br>
gctorture()<br>
dyn.load("testfft.so")<br>
for (i in 2:3) { # bombs on 1 but not 2 or 3<br>
print(.Call('testfft', 1:20, getNamespace("stats"), i) - fft(1:20))<br>
}<br>
cat("still here\n")<br>
-----------------------------------------------------------------------------<br>
<br>
<br>
edd@max:/tmp/samperi-gc$ r -lRcpp -e'Rcpp:::SHLIB("testfft.cpp")'<br>
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<br>
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<br>
edd@max:/tmp/samperi-gc$ r torture.R<br>
Loading required package: methods<br>
In case 2<br>
[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<br>
In case 3<br>
[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<br>
still here<br>
edd@max:/tmp/samperi-gc$<br>
<font color="#888888"><br>
--<br>
</font><div><div></div><div class="h5">Dirk Eddelbuettel | <a href="mailto:edd@debian.org">edd@debian.org</a> | <a href="http://dirk.eddelbuettel.com" target="_blank">http://dirk.eddelbuettel.com</a><br>
</div></div></blockquote></div><br>