破坏weak_ptr时崩溃,对weak_ptr的shared_ptr_emplace对象进行双重破坏

时间:2018-01-07 11:01:42

标签: c++ memory-management weak-ptr

我在调用weak_ptr的析构函数时偶尔遇到崩溃。这是精确的崩溃日志

tests(35405,0x700002602000) malloc: *** error for object 
0x7fcd2010a5b0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

它抱怨的指针是weak_ptr中保存的shared_ptr_emplace对象。 weak_ptr的析构函数看起来像这样

template<class _Tp>
weak_ptr<_Tp>::~weak_ptr()
{
  if (__cntrl_)
      __cntrl_->__release_weak();
}

它没有崩溃的__cntrl对象(在调用__release_weak时释放)。

以下是我试图完成的崩溃功能的高级描述。我异步运行USB事务,对于每个异步事务,我将weak_ptr返回给一个允许客户端取消异步事务的对象。我将其称为CancelableToken,它也继承自enable_shared_this。令牌的shared_ptr由底层事务持有。在崩溃时,事务已经完成,并且CancelableToken的shared_ptr已被释放,因此只存在一个weak_ptr引用(来自enable_shared_from_this的弱引用也被删除,因为CancelableToken的底层对象已被释放),由呼叫/等待功能的堆栈保持。这是方法

virtual bool ControlSend( uint32_t address, uint32_t value )
{
    bool retval = false;
    shared_ptr<promise<bool>> pPromise = make_shared<promise<bool>>();
    BootCommand cmd( BootCommand::BootCommandWrite, address, value );
    auto fut = pPromise->get_future();
    auto token = SendControlBytesVendorAsync( &cmd, sizeof( cmd ),
                                              [this, pPromise, cmd]( shared_ptr<AUsbTransfer> pTransfer ) {
                                                if( pTransfer->IsSuccessful()) {
                                                  DEBUG_PRINT( "Competed: 0x%x = 0x%x", cmd.address, cmd.value );
                                                  pPromise->set_value( true );
                                                } else {
                                                  DEBUG_PRINT( "ControlSend: Failed to send Control Bytes" );
                                                  pPromise->set_value( false );
                                                }
                                              } );
    if( fut.wait_for( m_timeout ) == future_status::ready ) {
      retval = fut.get();
      DEBUG_PRINT("Transaction Done 0x%x = 0x%x", cmd.address, cmd.value );
    } else {
      LOCK_AND_CANCEL( token );
    }
    DEBUG_PRINT( "Returning, token: %p", &token );
    return retval;
}

SendControlBytesVendorAsync()是一个成员函数,用于触发异步事务。当发送操作完成时,将调用传入的函数回调。回调被赋予一个shared_ptr给代表传输的对象(AUsbTransfer)。此Transfer对象是拥有CancelableToken的shared_ptr的对象。当回调退出时,pTransfer将被销毁并使用CancelableToken。

函数ControlSend()基本上是一个等待事务完成的阻塞函数。大多数情况下,该功能运行得很好,但每隔一段时间它就像我上面提到的那样崩溃。我曾尝试在没有崩溃的情况下使用调试器,当它崩溃并且无法真正看到差异时。我没有关于如何调试的想法,可以真正使用一些帮助。如果您需要我发布更多信息,请告诉我,我会。

0 个答案:

没有答案