2017-02-14 4 views
3

p->start()の後にどういうわけか - shared_from_thisがスローされたbad_weak_ptrです。
しかし、shared_ptrの後に呼び出されるp->start()が完全に開始されています。shared_ptrが別のスレッドから呼び出されたときにshared_ptrが初期化された後にbad_weak_ptrを取得する

struct A : std::enable_shared_from_this<A> 
{ 
    std::thread* t = nullptr; 
    A() {} 
    ~A(){ 
     t->join(); 
     delete t; 
    } 
    void f() { 
     try{ 
      auto p = this->shared_from_this(); 
      std::cout << "p:" << p.get() << "\n"; 
     } catch(...) { 
      std::cout << "Exception !!!\n"; 
     } 
    } 
    void start() { 
     t = new std::thread(&A::f,this); 
    } 
}; 
std::shared_ptr<A> create() { 
    A* a = new A(); 
    std::shared_ptr<A> p(a); 
    p->start(); 
    return p; 
} 
int main() 
{ 
    int i = 0; 
    std::map<int,std::shared_ptr<A>> map; 
    while(i < 1024) { 
     auto ptr = create(); 
     map[i++] = ptr; 
    } 
    return 0; 
} 

link to working code (coliru) - unexplained bad_weak_ptr - exception is thrown ...

+1

'main'が戻る前にすべてのスレッドに' join 'する必要があります。 – o11c

+1

私はAのdtorの各スレッドに参加しています。 Aのdtorは、mainのreturnの前にmapのdtorが呼び出されたときに呼び出されます。いずれにせよ、まだbad_weak_ptrについて説明していないようです。 – Roma

+0

なぜ 'std :: thread'を動的に割り当てるのですか? 'std :: thread'はスレッドへの移動専用のハンドルです。デフォルトでそれを構築してから新しい値を移動して割り当てることができます。 'std :: thread'オブジェクトに' new'/'delete'を使わないでください。 –

答えて

5

あなたの問題は、あなたがjoinに競合状態を持っているということです。 mainが終了し、マップ内のオブジェクトが破棄されている可能性があります。マップ内のshared_ptrが破壊され、オブジェクトのデストラクタを呼び出して呼び出されますが、遅すぎます。enable_shared_from_thisが使用したいのはshared_ptrです。オブジェクト自身のスレッドの中で(競合状態)、これをデッドweak_ptrで共有しようとすると、例外がスローされ、メッセージはcoutに出力されます。

関連する問題