Multithreading C++;11共享指针线程安全性是否已损坏?

Multithreading C++;11共享指针线程安全性是否已损坏?,multithreading,c++11,thread-safety,shared-ptr,Multithreading,C++11,Thread Safety,Shared Ptr,根据,共享_ptr的控制块是线程安全的。ie、operator=或reset可由多个线程访问,无需显式锁定。 但我看到一种奇怪的行为;有时会双重释放共享对象: #include <iostream> #include <memory> #include <unistd.h> using namespace std; class MyClass { public: MyClass(string x) : name(x) {cout<<"C

根据,共享_ptr的控制块是线程安全的。ie、operator=或reset可由多个线程访问,无需显式锁定。
但我看到一种奇怪的行为;有时会双重释放共享对象:

#include <iostream>
#include <memory>
#include <unistd.h>

using namespace std;

class MyClass {
public:
    MyClass(string x) : name(x) {cout<<"C->"<<name<<endl;};
    ~MyClass() {cerr<<"D->"<<name<<endl;};
    string name;
};

shared_ptr<MyClass> a;

void* tfunc(void*) {
  while(1){
   {
      shared_ptr<MyClass> s = a;
      usleep(5);
   }
  }
}

int main(void) {
    pthread_t threadid;
    a = make_shared<MyClass>("a");
    if(pthread_create(&threadid, NULL, tfunc, NULL)) {
        cout<<"pthread_create error"<<endl;
        return -1;
    }
    while(1){
      usleep(5);
      a = make_shared<MyClass>("b");
    }

    pthread_join(threadid, NULL);
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
类MyClass{
公众:

MyClass(字符串x):名称(x){coutNo.
=
reset
不是线程安全的。需要
std::atomic.
函数的
shared_ptr
重载


“控制块是线程安全的”意味着您可以在多个线程中使用
=
重置
(但每个线程使用单独的
共享\u ptr
),即使所有
shared\u ptr
对象都是彼此的副本

std::mutex
可能提供比
std::atomic
更好的解决方案。这意味着什么?如果sptr1=sptr2=make\u shared(“b”),将有多少个控制块?只有一个..对吗?如果这不是线程安全的,那么使用共享指针有什么意义。这不会让开发人员的生活成为噩梦吗?对于常规指针,开发人员可以控制托管对象的销毁。但共享ptr使其不确定。@VinodKd是的,将只有一个。但是您需要要在线程开始(或作为参数传递)之前而不是之后复制
共享\u ptr
==28588==ERROR: AddressSanitizer: heap-use-after-free on address 0xb33a7ad4 at pc 0x080490c4 bp 0xb54ff1d8 sp 0xb54ff1c8
WRITE of size 4 at 0xb33a7ad4 thread T1
    #0 0x80490c3 in __exchange_and_add /usr/include/c++/6/ext/atomicity.h:49
    #1 0x80491ed in __exchange_and_add_dispatch /usr/include/c++/6/ext/atomicity.h:82
    #2 0x8049a9e in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/6/bits/shared_ptr_base.h:147
    #3 0x80498a3 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/6/bits/shared_ptr_base.h:662
    #4 0x804977e in std::__shared_ptr<MyClass, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/6/bits/shared_ptr_base.h:928
    #5 0x8049797 in std::shared_ptr<MyClass>::~shared_ptr() /usr/include/c++/6/bits/shared_ptr.h:93
    #6 0x80492d7 in tfunc(void*) /tmp/main.cpp:19
    #7 0xb7248c4e  (/usr/lib/i386-linux-gnu/libasan.so.3+0x26c4e)
    #8 0xb6ea5304 in start_thread (/lib/i386-linux-gnu/libpthread.so.0+0x6304)
    #9 0xb6fb347d in __clone (/lib/i386-linux-gnu/libc.so.6+0xe947d)

0xb33a7ad4 is located 4 bytes inside of 36-byte region [0xb33a7ad0,0xb33a7af4)
freed by thread T0 here:
    #0 0xb72e7174 in operator delete(void*) (/usr/lib/i386-linux-gnu/libasan.so.3+0xc5174)
    #1 0x804ace0 in __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<MyClass, std::allocator<MyClass>, (__gnu_cxx::_Lock_policy)2> >::deallocate(std::_Sp_counted_ptr_inplace<MyClass, std::allocator<MyClass>, (__gnu_cxx::_Lock_policy)2>*, unsigned int) /usr/include/c++/6/ext/new_allocator.h:110
    #2 0x804ab07 in std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<MyClass, std::allocator<MyClass>, (__gnu_cxx::_Lock_policy)2> > >::deallocate(std::allocator<std::_Sp_counted_ptr_inplace<MyClass, std::allocator<MyClass>, (__gnu_cxx::_Lock_policy)2> >&, std::_Sp_counted_ptr_inplace<MyClass, std::allocator<MyClass>, (__gnu_cxx::_Lock_policy)2>*, unsigned int) /usr/include/c++/6/bits/alloc_traits.h:442
    #3 0x804a818 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<MyClass, std::allocator<MyClass>, (__gnu_cxx::_Lock_policy)2> > >::~__allocated_ptr() /usr/include/c++/6/bits/allocated_ptr.h:73
    #4 0x804b0aa in std::_Sp_counted_ptr_inplace<MyClass, std::allocator<MyClass>, (__gnu_cxx::_Lock_policy)2>::_M_destroy() /usr/include/c++/6/bits/shared_ptr_base.h:537
    #5 0x8049bbe in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/6/bits/shared_ptr_base.h:166
    #6 0x80498a3 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/6/bits/shared_ptr_base.h:662
    #7 0x804977e in std::__shared_ptr<MyClass, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/6/bits/shared_ptr_base.h:928
    #8 0x8049cd4 in std::__shared_ptr<MyClass, (__gnu_cxx::_Lock_policy)2>::operator=(std::__shared_ptr<MyClass, (__gnu_cxx::_Lock_policy)2>&&) /usr/include/c++/6/bits/shared_ptr_base.h:1003
    #9 0x8049a7c in std::shared_ptr<MyClass>::operator=(std::shared_ptr<MyClass>&&) /usr/include/c++/6/bits/shared_ptr.h:294
    #10 0x8049430 in main /tmp/main.cpp:35
    #11 0xb6ee2275 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18275)