[C++-sig] Bug and patch for boost.python with enable_shared_from_this

Ralf W. Grosse-Kunstleve rwgk at yahoo.com
Wed Feb 13 21:27:13 CET 2008

Hi Chad,

Could you at least ask Peter Dimov if he thinks the
dont_enable_shared_from_this patch could be generally useful?
Maybe he's OK adding it, then it wouldn't be a big deal
fixing Boost.Python, which would probably prevent a lot of
confusion and lost time in the future.



----- Original Message ----
From: Chad Austin <chad at imvu.com>
To: Development of Python/C++ integration <c++-sig at python.org>
Sent: Monday, February 11, 2008 10:10:31 PM
Subject: Re: [C++-sig] Bug and patch for boost.python with enable_shared_from_this

There probably is a way to prevent boost.python from creating
shared_ptrs with a null deleter like it does, but it would require far
more knowledge than I have.  :)

I agree that it would be a better fix, though.

On 2/11/08, Ralf W. Grosse-Kunstleve <rwgk at yahoo.com> wrote:
> Thanks for the patch! I'd love to check this in for you, but for the
> change in shared_ptr.hpp you'll need Peter Dimov's approval, and the
> shared_ptr documentation would have to be updated. Also, your reproducer
> should be turned into a unit test (in boost/libs/python/test).
> Is there any chance that the shared_ptr patch could somehow be avoided?
> Ralf
> ----- Original Message ----
> From: Chad Austin <chad at imvu.com>
> To: c++-sig at python.org
> Sent: Sunday, February 10, 2008 5:14:45 PM
> Subject: [C++-sig] Bug and patch for boost.python with enable_shared_from_this
> Hi all,
> A month ago or so we discovered a bug in Boost.Python that manifests when using enable_shared_from_this.  Here is a test case that demonstrates the bug:
> #include <boost/python.hpp>
> #include <boost/enable_shared_from_this.hpp>
> using namespace boost;
> using namespace boost::python;
> class Test;
> typedef shared_ptr<Test> TestPtr;
> class Test : public enable_shared_from_this<Test> {
> public:
>     static TestPtr construct() {
>         return TestPtr(new Test);
>     }
>     void act() {
>         TestPtr kungFuDeathGrip(shared_from_this());
>     }
>     void take(TestPtr t) {
>     }
> };
> void Export_test() {
>     class_<Test, TestPtr, noncopyable>("Test")
>         .def("construct", &Test::construct)
>         .staticmethod("construct")
>         .def("act", &Test::act)
>         .def("take", &Test::take)
>         ;
> }
> And here is the Python:
>         x = Test.construct()
>         x.take(x)
>         x.act()
> The bug (as I understand it) is that the shared_ptr_from_python converter creates a new shared_ptr for the Test instance to pass it into C++.  This new shared_ptr has a nop deleter, except that it keeps the Python object alive as long as the new shared_ptr is alive.  The problem here is that creating a shared_ptr to an object of type T when T is enable_shared_from_this<T> resets the weak pointer inside of enable_shared_from_this<T>.  (See shared_ptr's constructors for the details of the implementation.)  A fix that passes the test above and has worked for us is to change shared_ptr's constructor to accept a dont_enable_shared_from_this argument and pass that in from the shared_ptr_from_python converter.  The patch is attached (against boost 1.33, but the bug didn't look fixed in 1.34 either).
> Cheers,
> Chad
> p.s. I have seen other people with this problem as well.  Googling for bad_weak_ptr turns up several results.

More information about the Cplusplus-sig mailing list