Boost logo

Boost Users :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2008-08-03 14:43:35


I can at least explain why the problem occurs, but I'm not sure if I can
suggest a solution at this time.

The problem is that inside X::test there are two separate shared_ptr
instances pointing to the same A object. One has been created in main(), and
another has been created by Boost.Python for the x.test( a ) call in t1.py.

It so happens that the current behavior of enable_shared_from_this is for
the second instance to override the first one; that is, _internal_weak_this
is reinitialized from the 'pObj' argument when it's created.

Once 'pObj' goes out of scope, the weak_ptr expires, and shared_from_this
starts throwing bad_weak_ptr.

By using a raw pointer argument, you avoid this reinitialization.

We've been thinking of changing the behavior of enable_shared_from_this in
such cases, making it ignore subsequent shared_ptr instances to the same
object and having it stick to the first one. This, however, will not happen
for the upcoming 1.36 release of Boost.

You can in principle achieve the same result by patching your local copy of
Boost to make weak_ptr::_internal_assign only initialize when
this->expired() is true, but this has never been tested.

----- Original Message -----
From: "lxcypp lxc"
To: <boost-users_at_[hidden]>
Sent: Saturday, August 02, 2008 09:13
Subject: [Boost-users] A boost::python problem

> *I abstract the problem below:*
>
> t1.cpp:
>
> #include <boost/python.hpp>
> #include <boost/enable_shared_from_this.hpp>
> #include <boost/shared_ptr.hpp>
> #include <iostream>
> #include <string>
> #include <list>
> using namespace std;
> using namespace boost::python;
>
> static object mainobj, global;
>
> class A : public boost::enable_shared_from_this<A>
> {
> public:
> void test();
> };
>
> class X
> {
> public:
> void test(boost::shared_ptr<A> pObj){}
> };
>
> typedef boost::shared_ptr < A > A_ptr;
> typedef boost::shared_ptr < X > X_ptr;
>
> X_ptr xx;
>
> void A::test()
> {
> object aa = global[ "aa" ];
> A_ptr pa( shared_from_this() );
> aa( xx, pa );
> }
>
>
> BOOST_PYTHON_MODULE(pythonobject)
> {
> class_ <A>("A")
> .def("test", &A::test)
> ;
>
> class_ <X>("X")
> .def("test", &X::test)
> ;
>
> register_ptr_to_python <A_ptr>();
> register_ptr_to_python <X_ptr>();
> }
>
> int main()
> {
> Py_Initialize();
>
> initpythonobject();
> PyRun_SimpleString("import pythonobject");
> mainobj = import("__main__");
> global=(mainobj.attr("__dict__"));
>
> A_ptr a( new A );
> X_ptr x( new X );
> xx = x;
>
> try {
> exec_file("t1.py", global, global);
>
> a->test();
> a->test();
> a->test();
> } catch (error_already_set) {
> PyErr_Print();
> }
>
> return 0;
> }
>
> t1.py:
>
> #!/usr/bin/python
> #coding:utf-8
> def aa(x,a):
> x.test( a )
> return 1
>
>
> *after execute t1.cpp , I got this erro info:
>
> terminate called after throwing an instance of 'boost::bad_weak_ptr'
> what(): tr1::bad_weak_ptr
>
>
> When debug the program, I found after first "a->test()" call,
> a._internal_weak_this.use_count became 0. It's obviously wrong...
> so the after "a->test()" will cause error.
>
>
> But if change
> void test(boost::shared_ptr<A> pObj){}
> to
> void test(A* pObj){}
>
> I got no error. The errror is gone.
> Will someone explain this prolbem to me? Thank you.*


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net