C++11在多线程环境下多次发布shared_ptr



在g++4.8.5编译下,发现不正确使用sharedptr会导致shared_ptr的多次破坏。

伪代码:

#include<memory>
class Demo
{
public:
~Demo()
{
// Do something and cost some milliseconds
}    
};
typedef std::shared_ptr<Demo> DemoPtr;
DemoPtr global_demo;
DemoPtr instance() {return global_demo;}
// Main thread
int main()
{
global_demo = std::make_shared<Demo>();
// Do something
}
// Thread A
void thread_func()
{
// Do something

if(instance() != nullptr)
{
// Do something
}
// Do something
}

当主线程结束时,global_demo引用计数将减少到0,并且global_demo开始被销毁。当global_demo被破坏时,线程A调用instance((并做出判断,这导致global_demo的引用计数再次增加一,然后当释放局部变量时,引用计数再次减少到0,导致global_demo指向的对象被破坏。函数被再次调用。

查看gcc源代码:

//*************__shared_count***************//
__shared_count&
operator=(const __shared_count& __r) noexcept
{
_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
if (__tmp != _M_pi)
{
if (__tmp != 0)
__tmp->_M_add_ref_copy();
if (_M_pi != 0)
_M_pi->_M_release();
_M_pi = __tmp;
}
return *this;
}
//************_Sp_counted_base*****************//
void
_M_add_ref_copy()
{ __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }

那么,这是GCC错误吗?

在这种情况下,我应该使用std::weak_ptr来解决这个问题吗?那么,我的instance((方法代码是这样的吗?

DemoPtr instance() 
{
std::weak_ptr<Demo> w(global_demo);
if(!w.expired())
{
return w.lock();
}
return nullptr;
}

那么,这是GCC错误吗?

否。这是程序中的一个错误:

global_demo正在被破坏

线程A调用instance((

DemoPtr instance() {return global_demo;}

您正在复制一个生存期已结束(正在被销毁(的对象(return global_demo;(。程序的行为是未定义的。


在这种情况下,我应该使用std::weak_ptr来解决这个问题吗?

这不会修复错误。在从main返回之前,您必须连接任何依赖于静态变量的线程从技术上讲,在main返回后,在静态对象的析构函数内加入线程可能是可以的,只要该对象保证在依赖的静态对象之前被销毁。但祝你好运


对于某些线程,我无法控制结束。

然后必须避免在这些线程中使用任何静态变量。在本例中,创建global_demo的线程本地副本,并在线程中使用该副本。

相关内容

  • 没有找到相关文章

最新更新