[Rcpp-devel] gc() calls destructor twice when both class and XPtr deleted
Michael Shvartsman
mshvarts at umich.edu
Tue Feb 12 05:09:39 CET 2013
Yes, sorry for not being as quick with the follow-up, works exactly as
described and perfect for my purposes.
I now wonder whether I could've done this with RCPP_EXPOSED_CLASS
without creating and passing around the XPtr (at least, the module in
this example
http://romainfrancois.blog.free.fr/index.php?post/2012/10/25/Rcpp-modules-more-flexible
accepts and returns a pointer to a class without explicit as/wrap-ing to
XPtrs). But I'm quite happy with the solution Yan Zhou provided. Thanks
again,
Mike.
> Dirk Eddelbuettel <mailto:edd at debian.org>
> February 11, 2013 10:22 PM
> On 11 February 2013 at 19:10, Yan Zhou wrote:
> | 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.
>
> Nice work. Should have thought of the finalizer -- on quick testing
> this does
> indeed do the trick. Well done.
>
> Dirk
>
> Yan Zhou <mailto:zhouyan at me.com>
> February 11, 2013 2:10 PM
> 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
>
>
>
> Michael Shvartsman <mailto:mshvarts at umich.edu>
> February 11, 2013 1:55 PM
> 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 <mailto:edd at debian.org>
> 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 <mailto:mshvarts at umich.edu>
> 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()
> -----
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20130211/42218efa/attachment-0001.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/42218efa/attachment-0002.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/42218efa/attachment-0003.jpg>
More information about the Rcpp-devel
mailing list