[C++-sig] [Boost.Python] Why a bad_weak_ptr exception with get_shared_from_this?

John Trimble trimblej at gmail.com
Sun Feb 10 07:10:13 CET 2008


I'm having a slight issue when using get_shared_from_this() in a
member function when that function also gets as a parameter a
shared_ptr to itself. I've simplified my issue down to this short
example (complete sources also attached):

---------------------------
namespace test{
using namespace boost;
using namespace boost::python;

class A : public enable_shared_from_this<A> {
    public:
    virtual void attempt() {
        shared_ptr<A> ptr = shared_from_this();
    }

    virtual void attempt_with_self(shared_ptr<A> a) {
        shared_ptr<A> ptr = shared_from_this();
    }
};

shared_ptr<A> make_A_instance() {
    shared_ptr<A> p(new A());
    return p;
}
} // namespace test

BOOST_PYTHON_MODULE(test_module)
{
    using namespace boost;
    using namespace boost::python;

    register_ptr_to_python< shared_ptr<test::A> >();

    class_<test::A >("A", no_init)
        .def("attempt", &test::A::attempt)
        .def("attempt_with_self", &test::A::attempt_with_self)
        .def("__init__", make_constructor(&test::make_A_instance));
    ;
}
---------------------------

I'm using a custom constructor which always wraps new instances of A
in a shared_ptr, so the weak_ptr in any instance of A should always be
initialized. Upon testing this code I get the following result:

-------------------------------------------------
>>> a = A()
>>> a.attempt()
>>> a = A()
>>> a.attempt_with_self(a)
>>> a.attempt()
Traceback (most recent call last):
  File "test_error.py", line 12, in ?
    a.attempt() # bad_weak_ptr exception
RuntimeError: tr1::bad_weak_ptr
---------------------------

The bad_weak_ptr exception originates on the following line from A.attempt():

shared_ptr<A> ptr = shared_from_this();

Somehow my weak_ptr reference is getting invalidated by the
attempt_with_self(...) call. I tried doing this purely in C++ without
a problem:

---------------------------
shared_ptr<A> p = make_A_instance();
p->attempt_with_self(p);
p->attempt();
---------------------------

I'm guessing that the conversion to python of the shared_ptr<A>
returned by make_A_instance() is where the problem originates, but I
don't quite understand all the magic involved in that process to know
how to get around this issue. Any suggestions on how I might get this
working would be greatly appreciated. I imagine people do this kind of
thing regularly, so I'm probably missing some simple detail. I
apologize if this is a rather n00b question, but I've looked through
the docs and the mailing list and haven't found anything about this
specific issue.

Thanks,
- John Trimble
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: module_test.cpp
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20080209/f7305fca/attachment.txt>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test_error.py
Type: text/x-python
Size: 240 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20080209/f7305fca/attachment.py>


More information about the Cplusplus-sig mailing list