[Rcpp-devel] tracking volatile bug

Sokol Serguei serguei.sokol at gmail.com
Fri Nov 21 23:50:21 CET 2014


Thanks Martin,

Your PROTECT did the job :)

Martin Morgan has written at  Fri, 21 Nov 2014 13:33:47 -0800
> On 11/21/2014 09:23 AM, Serguei Sokol wrote:
>> Well, I could narrow the issue but not yet resolve it.
>>
>> Le 18/11/2014 20:46, William Dunlap a écrit :
>>>> I will try "gctorture(TRUE)" suggested by Martin.
>> I'll start with this easy part. Unfortunately valgrind
>> didn't detect any wrong access to memory.
>>
>> Now, the difficult part.
>> The most reduced code in cpp producing an error under
>> gctorture(TRUE) is the following:
>> 8<------------file matrix_norm.cpp
>> //[[Rcpp::depends(RcppArmadillo)]]
>> #include <RcppArmadillo.h>
>> using namespace Rcpp;
>> using namespace arma;
>>
>> // [[Rcpp::export]]
>> SEXP nmat(mat A) {
>>     Function Matrix_norm_r_=Environment("package:Matrix")["norm"];
>>     SEXP s=wrap("1");
>
> the reduced example is great. s is not PROTECT()ed, Rf_PrintValue(s) 
> almost certainly decides that it needs memory, and re-uses the SEXP 
> occupied by s for its own internal purposes. So simply
>
>   SEXP s = PROTECT(wrap("1"));
>   // ...
>   UNPROTECT(1)
>   return res;
>
If I did not use the protection in my Rcpp code it's because
I did not see it in any example of quick ref guide:
http://cran.r-project.org/web/packages/Rcpp/vignettes/Rcpp-quickref.pdf
I didn't see any mention of PROTECT necessity neither in
http://dirk.eddelbuettel.com/code/rcpp/Rcpp-introduction.pdf
especially in the part dedicated to the use of wrap().

> You _could_ figure out where Rf_PrintValue over-writes the unprotected 
> s SEXP,
It turns out that the memory is getting corrupted well before 
Rf_PrintValue. It
was here just to witness the devastation. The corruption occurred inside 
Rf_mkString()
as shown in the debug session.

> but that wouldn't be helpful in any way; R in general and 
> Rf_PrintValue in particular is allowed to write to unprotected SEXPs. 
> It's also not relevant in some ways what the error is -- invalid 
> 'type' or anything else -- just that the error occurs. Also, while not 
> strictly true, it is much more likely that protection errors are in 
> user code (as here), then in package code, and finally in R code itself.
>
> For what it's worth...
>
>>     Rf_PrintValue(s);
>>     SEXP res=Matrix_norm_r_(wrap(A), s);
>
> I think wrap(A) needs (in principle) to be PROTECT()ed, too.
For the sake of safety, I'll do it.

>
> Sometimes in simplifying the problem we introduce new errors; I think 
> your wrap()'s in the original code were immediately returned to the 
> user, so not in need of protection.
In the original code, there were not wraping at all for R function call.
I supposed (very naively, it is clear now) that necessary wrapping and
protection was automagicaly added behind the stage by Rcpp.

> I would set a breakpoint on Rf_error, then trigger the error under 
> gctorture(TRUE), then in gdb backtrace to localize which specific line 
> in your code triggers the error, and simplify around that.
That was I have done to find out that Rf_mkString() call was the last part
of Rcpp where corruption occurred.

Thank again.
Serguei.


More information about the Rcpp-devel mailing list