vendredi 15 février 2019

SIGABRT when deleting object moved to container

I have an interface:

struct Interface{
  Interface(const Interface &) = delete;
  auto operator = (const Interface &) -> Interface & = delete;
  virtual ~Interface() = 0;
};

I have an implementation:

struct Impl : public Interface {
  Impl(const Impl &) = delete;
  auto operator = (const Impl &) -> Impl & = delete;
  bool m_is_borrowed{false};
  std::weak_ptr<Pool> m_pool;

  ~Impl() {
    if (m_is_borrowed) {
      if (auto pool = m_pool.lock()) {
        m_is_borrowed = false;
        auto conn = std::unique_ptr<Interface>(this);
        pool->m_objects.push_back(std::move(conn));
      }
    }
  }
};

As the code indicates Pool has a member of type std::vector<std::unique_ptr<Interface>>

It also creates instances of Interface:

auto impl = std::unique_ptr<Interface>(new Implementation());
m_objects.push_back(std::move(impl));

And gives one to the user of Pool:

auto get() -> std::unique_ptr<Interface> {
  return std::move(m_objects.front());
}

So what I'm trying to do is, when an instance of Implementation is deleted, check if it's been borrowed from Pool and if that's the case, send it back to the pool. If it's in the pool, let it be deleted normally.

Sending the instance back to the pool works, but when I try to delete objects when Pool is deleted I get the following error:

integration(46154,0x1003855c0) malloc: *** error for object 0x101900000: pointer being freed was not allocated
integration(46154,0x1003855c0) malloc: *** set a breakpoint in malloc_error_break to debug

with the following stack trace:

* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff6418d23e libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff64243c1c libsystem_pthread.dylib`pthread_kill + 285
    frame #2: 0x00007fff640f61c9 libsystem_c.dylib`abort + 127
    frame #3: 0x00007fff642056e2 libsystem_malloc.dylib`malloc_vreport + 545
    frame #4: 0x00007fff642054a3 libsystem_malloc.dylib`malloc_report + 152
    frame #5: 0x000000010000fa82 integration`Implementation::~Implementation(this=0x0000000101900000) at Implementation.cpp:14
    frame #6: 0x000000010000a449 integration`std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~__vector_base() [inlined] std::__1::default_delete<Interface>::operator(this=0x0000000101800c58, __ptr=0x0000000101900000)(Interface*) const at memory:2285
    frame #7: 0x000000010000a421 integration`std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~__vector_base() [inlined] std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >::reset(this=0x0000000101800c58, __p=0x0000000000000000) at memory:2598
    frame #8: 0x000000010000a3b0 integration`std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~__vector_base() [inlined] std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >::~unique_ptr(this=0x0000000101800c58) at memory:2552
    frame #9: 0x000000010000a3b0 integration`std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~__vector_base() [inlined] std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >::~unique_ptr(this=0x0000000101800c58) at memory:2552
    frame #10: 0x000000010000a3b0 integration`std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~__vector_base() [inlined] std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > >::destroy(this=0x0000000101800a58, __p=0x0000000101800c58) at memory:1860
    frame #11: 0x000000010000a358 integration`std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~__vector_base() [inlined] void std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::__destroy<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > >(__a=0x0000000101800a58, __p=0x0000000101800c58) at memory:1727
    frame #12: 0x000000010000a33c integration`std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~__vector_base() [inlined] void std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::destroy<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > >(__a=0x0000000101800a58, __p=0x0000000101800c58) at memory:1595
    frame #13: 0x000000010000a320 integration`std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~__vector_base() [inlined] std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::__destruct_at_end(this=0x0000000101800a48, __new_last=0x0000000101800c50) at vector:413
    frame #14: 0x000000010000a297 integration`std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~__vector_base() [inlined] std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::clear(this=0x0000000101800a48) at vector:356
    frame #15: 0x000000010000a27f integration`std::__1::__vector_base<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~__vector_base(this=0x0000000101800a48) at vector:441
    frame #16: 0x000000010000a235 integration`std::__1::vector<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~vector(this=0x0000000101800a48 size=2) at iterator:1425
    frame #17: 0x0000000100002395 integration`std::__1::vector<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> >, std::__1::allocator<std::__1::unique_ptr<Interface, std::__1::default_delete<Interface> > > >::~vector(this=0x0000000101800a48 size=2) at iterator:1425
    frame #18: 0x0000000100002478 integration`Pool::~Pool(this=0x00000001018009d8) at Pool.cpp:17
    frame #19: 0x0000000100002565 integration`Pool::~Pool(this=0x00000001018009d8) at Pool.cpp:15
    frame #20: 0x0000000100167029 integration`std::__1::__shared_ptr_emplace<Pool, std::__1::allocator<Pool> >::__on_zero_shared(this=0x00000001018009c0) at memory:3656
    frame #21: 0x000000010000cc01 integration`std::__1::shared_ptr<Pool>::~shared_ptr() [inlined] std::__1::__shared_count::__release_shared(this=0x00000001018009c0) at memory:3490
    frame #22: 0x000000010000cbb7 integration`std::__1::shared_ptr<Pool>::~shared_ptr() [inlined] std::__1::__shared_weak_count::__release_shared(this=0x00000001018009c0) at memory:3532
    frame #23: 0x000000010000cbb7 integration`std::__1::shared_ptr<Pool>::~shared_ptr(this=0x00007ffeefbfe1a0) at memory:4468
    frame #24: 0x0000000100002da5 integration`std::__1::shared_ptr<Pool>::~shared_ptr(this=0x00007ffeefbfe1a0) at memory:4466
    frame #25: 0x0000000100165d1f integration`____C_A_T_C_H____T_E_S_T____0() at Pool.cpp:30
    frame #26: 0x00000001000516e3 integration`Catch::TestInvokerAsFunction::invoke(this=0x0000000100702b90) const at catch.hpp:11605
    frame #27: 0x000000010003e277 integration`Catch::TestCase::invoke(this=0x0000000101800760) const at catch.hpp:11506
    frame #28: 0x000000010003e16d integration`Catch::RunContext::invokeActiveTestCase(this=0x00007ffeefbff308) at catch.hpp:10365
    frame #29: 0x0000000100039abb integration`Catch::RunContext::runCurrentTest(this=0x00007ffeefbff308, redirectedCout="", redirectedCerr="") at catch.hpp:10339
    frame #30: 0x0000000100037387 integration`Catch::RunContext::runTest(this=0x00007ffeefbff308, testCase=0x0000000101800760) at catch.hpp:10115
    frame #31: 0x0000000100042c39 integration`Catch::(anonymous namespace)::runTests(config=std::__1::shared_ptr<Catch::Config>::element_type @ 0x0000000101800228 strong=4 weak=1) at catch.hpp:10667
    frame #32: 0x00000001000417e6 integration`Catch::Session::runInternal(this=0x00007ffeefbff780) at catch.hpp:10862
    frame #33: 0x00000001000414c5 integration`Catch::Session::run(this=0x00007ffeefbff780) at catch.hpp:10819
    frame #34: 0x000000010007ef8a integration`int Catch::Session::run<char>(this=0x00007ffeefbff780, argc=2, argv=0x00007ffeefbff8f8) at catch.hpp:10565
    frame #35: 0x000000010007eed2 integration`main(argc=2, argv=0x00007ffeefbff8f8) at catch.hpp:14318
    frame #36: 0x00007fff6404ded9 libdyld.dylib`start + 1
    frame #37: 0x00007fff6404ded9 libdyld.dylib`start + 1

Step by step debugging shows that when Pool is destroyed m_is_borrowed is false so no new unique_ptr instances are created. What could be causing this issue?

Aucun commentaire:

Enregistrer un commentaire