2017-06-20 8 views
2

c++11以降にスレッドセーフなシングルトンパターンを実装する方法を学習しています。std :: systemシングルトンオブジェクトをインスタンス化する際の例外

#include <iostream> 
#include <memory> 
#include <mutex> 

class Singleton 
{ 
public: 
    static Singleton& get_instance(); 
    void print(); 

private: 
    static std::unique_ptr<Singleton> m_instance; 
    static std::once_flag m_onceFlag; 
    Singleton(){}; 
    Singleton(const Singleton& src); 
    Singleton& operator=(const Singleton& rhs); 
}; 

std::unique_ptr<Singleton> Singleton::m_instance = nullptr; 
std::once_flag Singleton::m_onceFlag; 

Singleton& Singleton::get_instance(){ 
     std::call_once(m_onceFlag, [](){m_instance.reset(new Singleton());}); 
     return *m_instance.get(); 
}; 

void Singleton::print(){ 
    std::cout << "Something" << std::endl; 
} 

int main(int argc, char const *argv[]) 
{ 
    Singleton::get_instance().print(); 
    return 0; 
} 

コードは正常にコンパイルされますが、実行すると次の例外が発生します。

terminate called after throwing an instance of 'std::system_error' 
what(): Unknown error -1 
Aborted 

私はgdbでプログラムをデバッグしようとしました。 std::call_onceを呼び出すと例外がスローされたようです。何が起こっているのか分かりませんが、ラムダ式がオブジェクトを作成できなかったと仮定します。

2番目の質問です。未知のエラーコードが実際に意味するものを知る方法はありますか?私は-1は、問題を特定しようとするとあまり役に立たないと思います。

ありがとうございました。

+3

マイヤーズのシングルトンを使わないのはなぜですか? – Jarod42

+1

Jarodにスレッドの安全性について何かお答えする場合は、[this](https://stackoverflow.com/questions/1661529/is-meyers-implementation-of-singleton-pattern-thread-safe)を参照してください – StoryTeller

+0

@ Jarod42私はMeyerのシングルトンについて知っていただけです。多くの読書が先行しています:) – hannibal

答えて

4

これは、-pthreadフラグでコンパイルしておらず、システム上のネイティブスレッドライブラリのユーティリティを使用しようとしているために発生します。 「マイヤーズシングルトン」

Singleton& Singleton::get_instance(){ 
    static Singleton instance; 
    return instance; 
} 

これは、スレッドセーフである、とinstance変数のみが初期化されることになりますと呼ばれるあなたの例では、シングルトンパターン定義を次のように変更に代わる見た目として

一度。このウィキペディアの記事は、フードの中でどのように機能するのかをよく説明していますhttps://en.wikipedia.org/wiki/Double-checked_locking。可能であれば、コンパイラにコードをアレンジするのは良いことです。 Also as noted in the commentsこの質問にも便利な情報がありますIs Meyers' implementation of the Singleton pattern thread safe?

+0

ここで 'pthread'が必要な部分は? 「ネイティブスレッディングライブラリからユティリティを使用する」はどこで確認できますか? – VTT

+0

@VTT OPのコード中の ''ヘッダとそれに続く 'std :: call_once()'の呼び出しには同期が必要です – Curious

+0

''はC++の標準ライブラリヘッダの1つです:: :: std :: call_once'はC++の標準ライブラリルーチン。必要なライブラリがリンクされていない場合は、 "未解決の外部シンボル..."というエラーが発生しています。 – VTT

関連する問題