[Rcpp-devel] gc() calls destructor twice when both class and XPtr deleted

Yan Zhou zhouyan at me.com
Mon Feb 11 20:10:41 CET 2013


It seems to me that XPtr is like an ownership pointer. It is much like unique_ptr. What you need here is a non-owning reference pointer, like weak_ptr.

Have you tried

XPtr<A> A::getPtr(){
   return(XPtr<A>(this, false));
}

With the optional argument, a finalizer is not set and the gc will not delete the C++ object. I haven't used XPtr in this way, but from the document I guess this shall work.

Best,

Yan Zhou

On Feb 11, 2013, at 6:55 PM, Michael Shvartsman <mshvarts at umich.edu> wrote:

> Hi Dirk -- 
> 
>     Thanks for the quick response. My design is (I think) textbook aggregation -- in my case, A is a logger class and B is an experiment class. The experiment calls methods from the logger, but the logger may be active for more than one experiment so it can't be created inside it. So I create the logger and pass a pointer to it into the experiment. There are definitely other ways to design this, but this way doesn't seem to be particularly unreasonable. 
> 
>     The basic goal is to create a C++ object on the R side (in this case, the logger class) and pass it back down to the C++ side for later use by another C++ object (the experiment class). I thought that XPtr was the right way to do this (based on e.g. http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2011-December/003214.html), but I could be misunderstanding either XPtrs or the example in that email. If there is a different way to pass down the Rcpp class and unwrap it to arrive at a pointer to the underlying C++ class, it would be great. Best, 
> 
>         Mike. 
>> 	Dirk Eddelbuettel	February 11, 2013 12:40 PM
>> On 11 February 2013 at 12:16, Michael Shvartsman wrote:
>> | Hi Rcpp-devel -
>> | 
>> | In some of my code, I return an XPtr pointing to one C++ class 
>> | (e.g. class A) to the R side, and then pass it back down to the C++ side 
>> | in the constructor of another class (e.g. class B, which needs access to 
>> | some methods in class A). If I rm() both class A and the pointer to it 
>> | on the R side (or they otherwise both go out of scope), then the garbage 
>> | collector calls the destructor of class A twice and attempts to free the 
>> | memory twice.
>> | 
>> | Happens on OSX and Ubuntu with latest R and Rcpp. Is this intended 
>> | behavior? If yes, what's a recommended workaround? I can go into more 
>> | detail on why this is useful to my workflow if needed. Below is a 
>> | minimal example. Best,
>> 
>> Thanks for sending a complete example -- very helpful.
>> 
>> I will think about this some more, but my first gut reaction is that your
>> design is wrong. You are essentially "just" using XPtr to get two references
>> to the same memory, and then for all intends and purposes doing
>> 
>> x = new Something;
>> delete x;
>> delete x;
>> 
>> which also doesn't work. I have worked quite happily with XPtr in the past,
>> and so have others. I have however not mixed them with Modules, I think, so
>> maybe that enters.
>> 
>> But I think the best answers to the "I hurts when I do this" remains "well
>> then just don't it". 
>> 
>> And I may well have missed something here...
>> 
>> Dirk
>> 
>> | 
>> | Mike Shvartsman.
>> | 
>> | -----
>> | library(Rcpp)
>> | library(inline)
>> | 
>> | inc <- '
>> | using namespace Rcpp;
>> | class A{
>> | public:
>> | A();
>> | ~A();
>> | XPtr<A> getPtr();
>> | };
>> | 
>> | XPtr<A> A::getPtr(){
>> | return(XPtr<A>(this));
>> | }
>> | 
>> | A::A(){
>> | Rcout << "CTOR" << std::endl;
>> | }
>> | 
>> | A::~A(){
>> | Rcout << "DTOR" << std::endl;
>> | }
>> | 
>> | RCPP_MODULE(mod){
>> | class_<A>("A")
>> | .constructor()
>> | .method("getPtr", &A::getPtr)
>> | ;
>> | }
>> | '
>> | 
>> | func <- cxxfunction(signature(), include=inc, plugin='Rcpp')
>> | 
>> | mod <- Module('mod', getDynLib(func))
>> | 
>> | 
>> | A <- mod$A
>> | 
>> | a <- new(A)
>> | aPtr <- a$getPtr()
>> | rm(a)
>> | rm(aPtr)
>> | gc()
>> | -----
>> | 
>> | _______________________________________________
>> | 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
>> 
>> 	Michael Shvartsman	February 11, 2013 12:16 PM
>> Hi Rcpp-devel - 
>> 
>>     In some of my code, I return an XPtr pointing to one C++ class (e.g. class A) to the R side, and then pass it back down to the C++ side in the constructor of another class (e.g. class B, which needs access to some methods in class A). If I rm() both class A and the pointer to it on the R side (or they otherwise both go out of scope), then the garbage collector calls the destructor of class A twice and attempts to free the memory twice. 
>> 
>>     Happens on OSX and Ubuntu with latest R and Rcpp. Is this intended behavior? If yes, what's a recommended workaround? I can go into more detail on why this is useful to my workflow if needed. Below is a minimal example. Best, 
>> 
>>         Mike Shvartsman. 
>> 
>> ----- 
>> library(Rcpp) 
>> library(inline) 
>> 
>> inc <- ' 
>> using namespace Rcpp; 
>> class A{ 
>>     public: 
>>         A(); 
>>         ~A(); 
>>         XPtr<A> getPtr(); 
>> }; 
>> 
>> XPtr<A> A::getPtr(){ 
>>     return(XPtr<A>(this)); 
>> } 
>> 
>> A::A(){ 
>>     Rcout << "CTOR" << std::endl; 
>> } 
>> 
>> A::~A(){ 
>>     Rcout << "DTOR" << std::endl; 
>> } 
>> 
>> RCPP_MODULE(mod){ 
>>     class_<A>("A") 
>>     .constructor() 
>>     .method("getPtr", &A::getPtr) 
>>     ; 
>> } 
>> ' 
>> 
>> func <- cxxfunction(signature(), include=inc, plugin='Rcpp') 
>> 
>> mod <- Module('mod', getDynLib(func)) 
>> 
>> 
>> A <- mod$A 
>> 
>> a <- new(A) 
>> aPtr <- a$getPtr() 
>> rm(a) 
>> rm(aPtr) 
>> gc() 
>> ----- 
>> 
> _______________________________________________
> 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/20130211/2aa7f16a/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: postbox-contact.jpg
Type: image/jpeg
Size: 1228 bytes
Desc: not available
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20130211/2aa7f16a/attachment.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: compose-unknown-contact.jpg
Type: image/jpeg
Size: 770 bytes
Desc: not available
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20130211/2aa7f16a/attachment-0001.jpg>


More information about the Rcpp-devel mailing list