| Store | Cart

[C++-sig] Boost-Python: Inconsistent shared_ptr use-count since Boost 1.63

From: Charlie Dyson <char...@charliedyson.net>
Fri, 26 Jan 2018 15:27:34 +0000
I believe the following behaviour changes in 1.63 judging by the
ChangeLog, though unfortunately I can only test 1.60 vs 1.66 at the
moment. Using Enterprise Linux 7 with gcc 7.2.

Consider this module:

#include <boost/python.hpp>
#include <iostream>
#include <memory>

namespace bp = boost::python;

struct X
{
  ~X () { std::cout << "Bye bye" << std::endl; }
};

BOOST_PYTHON_MODULE (pymodule)
{
  bp::class_<X, std::shared_ptr<X>> x_wrap ("X");

  // Not needed in newer boost
  bp::register_ptr_to_python<std::shared_ptr<X>> ();

  auto x1 = std::make_shared<X> ();
  auto x2 = bp::extract<std::shared_ptr<X>> (bp::object (x1)) ();

  // On a newer boost: use counts are not the same
  std::cout << x1.get () << ": "<< x1.use_count () << std::endl; // 2
  std::cout << x2.get () << ": "<< x2.use_count () << std::endl; // 1 :(
}

For the older Boost, the reference counts are both two, but they are 2
and 1 respectively in the newer Boost. Is this expected? I wonder if
there's some cleverness involving x2 somehow pointing to a BP object
that in turn points to x1. Curiously X appears to only be destructed
once, so it doesn't look like UB.

Where it bites me is cleanup time. If I add the following to the end
of the module, I get a segfault:

  static std::vector<std::shared_ptr<X>> v {x2};

Backtrace as follows:
#0  subtype_dealloc (self=0x7ffff7e24050) at Objects/typeobject.c:955
#1  0x00007fffef9dfb59 in xdecref<_object> (p=<optimized out>) at
./boost/python/refcount.hpp:38
#2  reset (this=0x6c1f30) at ./boost/python/handle.hpp:222
#3  boost::python::converter::shared_ptr_deleter::operator()
(this=0x6c1f30) at libs/python/src/converter/builtin_converters.cpp:35
#4  0x00007ffff7ff563a in _M_release (this=0x6c1f20) at
.../bits/shared_ptr_base.h:154
#5  ~__shared_count (this=<optimized out>, __in_chrg=<optimized out>)
    at .../bits/shared_ptr_base.h:684
#6  ~__shared_ptr (this=<optimized out>, __in_chrg=<optimized out>)
    at .../bits/shared_ptr_base.h:1123
#7  ~shared_ptr (this=<optimized out>, __in_chrg=<optimized out>) at
.../bits/shared_ptr.h:93
#8  _Destroy<std::shared_ptr<X> > (__pointer=<optimized out>) at
.../bits/stl_construct.h:98
#9  __destroy<std::shared_ptr<X>*> (__last=<optimized out>, __first=0x678920)
    at .../bits/stl_construct.h:108
#10 _Destroy<std::shared_ptr<X>*> (__last=<optimized out>,
__first=<optimized out>)
    at .../bits/stl_construct.h:137
#11 _Destroy<std::shared_ptr<X>*, std::shared_ptr<X> >
(__last=0x678930, __first=<optimized out>)
    at .../bits/stl_construct.h:206
#12 std::vector<std::shared_ptr<X>, std::allocator<std::shared_ptr<X>
> >::~vector (this=0x7ffff7ff7a60 <init_module_pymodule()::v>,
    __in_chrg=<optimized out>) at .../bits/stl_vector.h:434
#13 0x00007ffff6d24e69 in __run_exit_handlers () from /lib64/libc.so.6
#14 0x00007ffff6d24eb5 in exit () from /lib64/libc.so.6
#15 0x00007ffff6d0db1c in __libc_start_main () from /lib64/libc.so.6
#16 0x00000000004007a1 in _start ()

Is this a new behaviour change, or a bug, or was it always dangerous
and I have just been lucky until now?

Many thanks,

Charlie
_______________________________________________
Cplusplus-sig mailing list
Cplu...@python.org
https://mail.python.org/mailman/listinfo/cplusplus-sig

Recent Messages in this Thread
Charlie Dyson Jan 26, 2018 03:27 pm