2017-09-13 3 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의 싱글 톤 패턴] (https://stackoverflow.com/questions/1008019/c-singleton-design-pattern)을 고수하십시오. – user0042

+0

싱글 톤에는 아무런 문제가 없습니다. 이 특정 구현에는 두 가지 문제가 있습니다. 1) 싱글 톤 수명을 제어하지 않았습니다. 인스턴스 메서드를 얻는 첫 번째 호출에서 싱글 톤을 만드는 것은 결코 좋은 생각이 아닙니다. 2) 라이브러리는 부모 응용 프로그램에서 생성 한 싱글 톤을 요청하는 대신 자체 싱글 톤을 만듭니다. 이'instance()'메소드를 수정하려면 메인 애플리케이션에서 가져와야합니다. 추신 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

첫 번째 싱글 톤 (예 : 로깅 싱글 톤)에 액세스하려고하면 두 번째 싱글 톤을 사용하자마자 작동이 멈 춥니 다. 그럼 당신은 그것을위한 할당 방법을 가져야합니다. 그것은 다소 목적을 상실합니다. – Pfaeff

+0

누군가가 도움을 줄 게시물을 투표하기 전에 응답을 기다리는 데 잠시 시간을 할애 할 수 있습니까? 나는이 동기가 어디에서 유래하는지 결코 이해할 수 없을 것이다. 나는 단지 악의적 인 의도와 큰 과실에 대해서만 투표를합니다. 이 점은 valgrind 테스트 코드이며 메모리 누수없이 MRI 시스템에서 하루 종일 실행됩니다. 위에서 제공 한 것은 모든 공유 객체가 사적 Matrix를위한 로컬 작업 공간을 가지며 재구성 서비스를위한 글로벌 작업 공간을 통해 체인 아래의 재구성 단계로 전달할 수있게합니다. 진심으로, 나는 몇몇 사람들을 얻지 않을 것이다. –

+0

그래서 모든 싱글 톤을 하나의 작업 공간 객체에 묶어 라이브러리에 할당하겠습니까? 싱글 톤이 서로 액세스해야한다면 어떻게 될까요? 구성 싱글 톤에서 로그 수준을 결정하려고하는 로깅 싱글 톤을 가정 해 봅시다. – Pfaeff