J'ai un programme qui utilise un singleton. Ce programme charge une bibliothèque d'objets partagés lors de l'exécution. Cette bibliothèque utilise également le même singleton. Le problème est que lorsque vous accédez au singleton à partir de la bibliothèque, une nouvelle instance du singleton est créée.Chargement dynamique et singlesons
Le programme est lié à -rdynamic
, j'utilise -fPIC
pour les deux et le chargement se passe comme ceci:
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));
}
La bibliothèque exporte une classe comme ceci:
Module* make_instance()
{
return new HelloWorld();
}
struct export_vtable
{
Module* (*make)(void);
};
struct export_vtable exports = { make_instance };
et cette classe fait un usage du singleton.
Voici comment le singleton est créé (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_;
}
Le programme et le lien de la bibliothèque contre la Configuration.cpp
. Si je l'omets de la bibliothèque, j'obtiens une erreur de symbole indéfinie lorsque j'essaie d'accéder au singleton.
Quelqu'un a eu une idée pour résoudre ce problème? Merci beaucoup!
C'est l'une des raisons pour lesquelles les singletons sont une mauvaise idée. Ils ne fonctionnent pas comme prévu avec les bibliothèques liées dynamiquement. De même, tenez-vous plutôt à [Singleton Pattern de Scott Meyer] (https://stackoverflow.com/questions/1008019/c-singleton-design-pattern). – user0042
Il n'y a rien de mal avec les singletons. Il y a deux problèmes avec cette implémentation particulière: 1) Vous avez abandonné le contrôle sur la durée de vie singleton. Créer singleton au premier appel de la méthode d'obtention d'instance n'est jamais une bonne idée. 2) Votre bibliothèque crée son propre singleton au lieu de demander singleton créé par l'application parente. Pour corriger cette 'instance()' méthode devrait être importé de l'application principale. P.S. Singleton Pattern de Scott Meyer devrait s'appeler Antipattern. – VTT
Il devrait être possible de réutiliser le même singleton à l'intérieur de la bibliothèque, n'est-ce pas? Le problème semble être le singleton à l'intérieur de la bibliothèque qui observe l'autre. Avoir une méthode 'setConfiguration()' ou quelque chose dans la bibliothèque n'est pas non plus une option pour moi, car cela va un peu à l'encontre du but. ** EDIT: ** qu'entendez-vous par "importé de l'application principale"? – Pfaeff