[C++-sig] Re: Problem: held type, std::auto_ptr, ReferenceErrors.

David Abrahams dave at boost-consulting.com
Sat Aug 23 04:17:01 CEST 2003

Prabhu Ramachandran <prabhu at aero.iitm.ernet.in> writes:

> Problem 1: 
> ^^^^^^^^^^
> First spot of trouble is here:
> b.f():
> B::f
> func(b):
> B::f
> x.f():
> B::f
> func(x):
> Traceback (most recent call last):
>   File "test_holder.py", line 13, in ?
>     func(x)
> Boost.Python.ArgumentError: Python argument types in
>     B.f(B)
> did not match C++ signature:
>     f(Q227_GLOBAL_.N.holder.cppO3zZAb9B_Wrapper {lvalue})
>     f(1B {lvalue})

If you pass this through c++filt you'll see that it has a Python
object of type (Python) B but can't match it to a C++ function
requiring a (C++) B lvalue argument.  That can only mean that there's
no C++ B object in the Python B object.  Given that you're holding
these things by auto_ptr, which gives up ownership when copied, it's a
strong hint that the object has been passed where a C++ std::auto_ptr
object was expected, e.g. to your add_wrapper function.

> If I remove the HeldType and leave it as it is, everything works fine
> upto the func(x) call that is.  

And then... what?

> I also tried by specifying a boost::shared_ptr<T> as the held type.
> I did not need to use the add_wrapper in these two cases.  That also
> seems to work just fine.  

It sounds like you're very confused about object ownership issues in
all these cases.  

> So this looks to be a bug similar to the one earlier where x.f()
> used to fail when the held type was std::auto_ptr<T>.  AFAIK, this
> does not look to be a problem with Pyste.

If you really think this is a bug in Boost.Python itself then please
reduce the Pyste-generated code and associated Python to a minimal
case so we can see what's really going on.

> Problem 2: 
> ^^^^^^^^^^
> The second problem is with the f(h) call.  I get the following error
> when I use either std::auto_ptr<T> or boost::shared_ptr<T> as the held
> type or use no held type at all.
> f(h):
> 1
> Traceback (most recent call last):
>   File "test_holder.py", line 15, in ?
>     f(h)
> ReferenceError: Attempt to return dangling pointer to object of type: 1A
> I also tried to use a return_internal_reference<1>(); instead of the
> return_value_policy(reference_existing_object)) and get the same
> results.  I also changed the HBase* argument to a Holder* argument
> with the same results.

Sounds like you're just flailing about here; think about what actually
goes on instead.  The HBase* passed to f actually points to a
Holder_Wrapper generated by Pyste so that you can override a Holder's
virtual functions in Python.  Its get() implementation looks up a
Python get method and calls that.  Holder's get() function returns a
new Python object (which simply points at the referenced object), to
which there is only one reference.  The dangling reference detector
doesn't know anything about the fact that this object is merely
pointing at some existing object - it assumes the Python object has
ownership of the C++ object it holds, and that C++ object will die
when the Python object does.

> I'd appreciate very much if someone can tell me what I am doing wrong
> here or if this is a bug.

Well, I don't know if this latter thing is a bug or a missing feature
exactly... but clearly something ought to be done about it.  I'm not
really sure what the best general solution is, though.  There are lots
of ways the dangling reference detector can be too conservative.  For
example, if the C++ object is held by shared_ptr, there may be other
shared_ptr copies keeping it alive.  I don't really want to try to
solve the problem until I understand what the right solution might be.

Dave Abrahams
Boost Consulting

More information about the Cplusplus-sig mailing list