2017-09-13 7 views
0

シングルトンを使用するプログラムがあります。このプログラムは、実行時に共有オブジェクトライブラリをロードします。このライブラリは同じシングルトンも使用します。 問題は、ライブラリからシングルトンにアクセスするときに、シングルトンの新しいインスタンスが作成されることです。ランタイム動的ロードとシングルトン

プログラムが-rdynamicとリンクされて、私は両方のために-fPICを使用してロードは次のように起こる:

std::shared_ptr<Module> createModuleObject(const std::string& filename) 
{ 
    if (!fs::exists(filename)) 
     throw std::runtime_error("Library not found: " + std::string(filename)); 

    struct export_vtable* imports; 
    void *handle = dlopen(filename.c_str(), RTLD_LAZY | RTLD_GLOBAL); 

    if (handle) { 
     imports = static_cast<export_vtable*>(dlsym(handle, "exports")); 
     if (imports) 
      return std::shared_ptr<Module>(imports->make()); 
     else 
      throw std::runtime_error("Error trying to find exported function in library!"); 
    } else 
     throw std::runtime_error("Error trying to load library: " + std::string(filename)); 
} 

ライブラリは、このようなクラスにエクスポート:

Module* make_instance() 
{ 
    return new HelloWorld(); 
} 
struct export_vtable 
{ 
    Module* (*make)(void); 
}; 
struct export_vtable exports = { make_instance }; 

をし、そのクラスには、利用していますシングルトンの

これは、シングルトンの作成方法(Configuration.cpp)です:

std::unique_ptr<Configuration> Configuration::instance_(nullptr); 
std::once_flag Configuration::onlyOnceFlag_; 

Configuration& Configuration::instance() 
{ 
    if (instance_ == nullptr) 
    { 
     std::cout << "INSTANCE IS NULL, CREATING NEW ONE" << std::endl; 
     std::call_once(Configuration::onlyOnceFlag_, 
        [] { 
          Configuration::instance_.reset(new Configuration()); 
         }); 
    } 

    return *Configuration::instance_; 
}  

プログラムとConfiguration.cppに対するライブラリリンクの両方。ライブラリから省略した場合、シングルトンにアクセスしようとすると、未定義のシンボルエラーが発生します。

誰でもこの問題を解決する方法がありますか?どうもありがとうございました!

+1

です。動的リンクライブラリでは意図したとおりに動作しません。また、[Scott MeyerのSingleton Pattern](https://stackoverflow.com/questions/1008019/c-singleton-design-pattern)に固執してください。 – user0042

+0

シングルトンには何も問題ありません。この特定のインプリメンテーションには2つの問題があります。1)シングルトンのライフタイムを制御できない。最初にインスタンスメソッドを呼び出す際にシングルトンを作成することは決して良い考えではありません。 2)あなたのライブラリは、親アプリケーションによって作成されたシングルトンを要求するのではなく、独自のシングルトンを作成します。この 'instance()'メソッドを修正するには、メインアプリケーションからインポートする必要があります。 P.S. Scott MeyerのSingleton Patternは、Antipatternと呼ばれるべきです。 – VTT

+0

ライブラリ内で同じシングルトンを再利用することは可能でしょうか?そうではありませんか?問題は、他のものを隠しているライブラリ内のシングルトンであるようです。 'setConfiguration()'メソッドなどをライブラリに持たせることは、私にとってはあまり意味がありません。 **編集:**「メインアプリケーションからインポートする」とはどういう意味ですか? – Pfaeff

答えて

0

私はそれをどのように解決したのですかhttps://github.com/kvahed/codeare/blob/master/src/core/ReconStrategy.hpp 共有オブジェクトをロードした後、グローバルシングルトンWorkspaceのインスタンスをdllのロードされたクラスに割り当てます。 https://github.com/kvahed/codeare/tree/master/src/modulesのすべてのクラスは、ReconStrategyおよび共有オブジェクトから派生しています。良いことは、このコードは移植性があるということです。このようReconStrategyを構築する場合

これが起こる:

ReconContext::ReconContext (const char* name) { 
    m_dlib = LoadModule ((char*)name); 
    if (m_dlib) { 
    create_t* create = (create_t*) GetFunction (m_dlib, (char*)"create"); 
    m_strategy = create(); 
    m_strategy->Name (name); 
    m_strategy->WSpace (&Workspace::Instance()); 
    } else { 
     m_strategy = 0; 
    } 
    } 
} 

ここで重要なラインは、シングルトンは悪い考えている理由の一つだm_strategy->WSpace (&Workspace::Instance());

+0

最初のログにアクセスしようとする2番目のシングルトン(ログ記録シングルトンなど)があるとすぐに動作を停止します。それでは、あなたはそれの割り当て方法も持っていなければなりません。それはちょっと目的を破る。 – Pfaeff

+0

誰かが助けを求める投稿を投票する前に、応答を待つのに時間がかかりますか?私はこのモチベーションがどこから来るのか分かりません。私は悪意のある意向と大きな過失を投票します。 これは、テストされたコードを評価し、メモリリークなどのないMRIマシンで終日実行される点です。上記で私が提供しているのは、すべての共有オブジェクトがプライベートMatrix用のローカルワークスペースと再構築サービス用のグローバルワークスペースを持ってチェーンを再構築ステップに渡すことができるようにすることです。 真剣に、私はいくつかの人々を取得しません。 –

+0

したがって、すべてのシングルトンを単一のワークスペースオブジェクトにまとめてライブラリに割り当てることはできますか?シングルトンが互いにアクセスする必要がある場合はどうなりますか?構成シングルトンからログレベルを判断しようとするログ記録シングルトンを考えてみましょう – Pfaeff

関連する問題