std::shared_ptr 在线程中使用时崩溃
std::shared_ptr crashing when used in threads
在线程 1 中(释义代码):
std::vector<std::shared_ptr<Object>> list;
// Initialization
list.reserve(prop_count);
for (size_t i = 0; i < count; ++i)
{
list.push_back(std::shared_ptr<Object>());
}
// Looped code
for (auto iter = indexes.begin(); iter != indexes.end(); ++iter)
{
uint32_t i = *iter;
std::shared_ptr<Object> item = make_object(table->data[i]); // returns a shared_ptr of Object
list[i].swap(item);
}
在线程 2(释义代码)中:
for(auto iter = list.begin(); iter != list.end(); ++iter)
{
shared_ptr<Property> o(*iter);
if(o)
{
// some work with casting it
// dynamic_pointer_cast
}
} // <--- crashes here (after o is out of scope)
下面是调用堆栈:
0x006ea218 C/C++
std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)1>::_M_release(this = 0x505240) C/C++
std::__shared_count<(__gnu_cxx::_Lock_policy)1>::~__shared_count(this = 0xb637dc94) C/C++
std::__shared_ptr<Property, (__gnu_cxx::_Lock_policy)1>::~__shared_ptr(this = 0xb637dc90) C/C++
std::shared_ptr<Property>::~shared_ptr(this = 0xb637dc90) C/C++
startSending() C/C++
libpthread.so.0!start_thread() C/C++
libc.so.6 + 0xb52b8 C/C++
查看 shared_ptr_base.h,它似乎在这里崩溃:
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
{
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
_M_dispose(); // <--- HERE
我不确定如何解决这个问题。任何帮助,不胜感激。谢谢!
从 http://en.cppreference.com/w/cpp/memory/shared_ptr 开始,我的强调是添加的:
如果多个执行线程访问同一shared_ptr 如果没有同步,并且这些访问中的任何一个都使用非 const 的成员函数shared_ptr则会发生数据竞争;这 原子函数的shared_ptr重载可用于防止 数据竞赛。
在这种情况下,list[i]
和 *iter
是相同的实例。
对于线程 1,建议使用 std::atomic_store(&list[i], item)
而不是list[i].swap(item)
对于线程 2,建议使用 std::shared_ptr<Property> o(std::atomic_load(&*iter))
而不是std::shared_ptr<Property> o(*iter);
这一切都假设向量的大小不会改变,并引入容器的线程安全、迭代器失效等问题。不过,这超出了这个问题的范围,并在其他地方进行了介绍。
1)将数据放入容器:使用队列,而不是向量。不要保留和交换,只需将它们推到队列中即可。2) 每次推送都需要由互斥锁(类成员)保护。
====== 第二个线程 =======
3)队列的POP值,每个POP都需要由与上面相同的互斥锁保护。
请参阅:在生产者-消费者情况下使用条件变量
是的,您可以添加和使用互斥锁。 这可能会像描述的那样工作。这违背了目的。 另一个要维护的互斥锁和一个争用点是典型的。 尽可能选择原子而不是互斥体,您的无互斥体原子性能将感谢您。
- 当回溯以零开始时,如何调试崩溃
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 程序崩溃并显示"std::out_of_range"错误
- CoInitialize()在单独的线程上崩溃而不返回
- 使用调试/崩溃报告将应用程序部署到客户端
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 为什么我的多线程作业队列崩溃
- ExtractIconEx:可以工作,但偶尔会崩溃
- 为什么引用传递会导致此崩溃(C++)
- 试图创建流或fopen时程序崩溃
- 类对象数组的问题会导致崩溃
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 为什么要增加导致崩溃的指针
- 在虚幻引擎中删除NXOpen对象时崩溃
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- Visual Studio在尝试读取resource.txt文件时崩溃
- 将方法转换为调用该方法的成员函子对象会导致崩溃