2 votes

Les symboles de la bibliothèque statique sont parfois liés à l'exécutable, parfois non.

J'ai une bibliothèque statique qui est générée à partir de plusieurs fichiers cpp sous linux en utilisant g++. Un fichier d'en-tête contient une classe qui implémente le modèle de la fabrique.

pseudo-code dans le fichier d'en-tête comme ci-dessous

class Factory
{
public:
    static Factory& instance();
    Base * create(const std::string& name);
    template<class T>
      void register_class(const std::string& name);
}

template <class T>
class FactoryRegister
{
public:
    FactoryRegister(const std::string& name)
    {
       Factory::instance().register_class<T>(name);
    }
}

Le fichier cpp pour Factory contient les implémentations. Dans un autre fichier cpp Derive.cpp, il y a une classe que je veux enregistrer dans Factory. et j'ai défini une variable globale pour le faire. le code est le suivant

FactoryRegister<Derive> g_register_derive("derive");

tous ces fichiers sont compilés dans une bibliothèque statique et sont liés à un exécutable.

Si je comprends bien, comme le g_register_derive n'est référencé par aucun code, il ne devrait pas être lié à l'exécutable à moins que l'option whole-archive soit fournie.

La partie étrange est que si je mets g_register_derive dans Derive.cpp, il est vrai que ce symbole n'est pas lié à l'exécutable. Mais si je mets g_register_derive dans Factory.cpp, il est lié à l'exécutable.

J'ai utilisé nm pour vérifier le résultat, et il y a aussi une ligne de code qui appelle Factory::instance().create("Derive") qui peut aussi être utilisé pour vérifier si g_register_derive est lié ou non.

et bien sûr si je fournis l'option whole-archive, g_register_derive sera toujours lié à l'exécutable.

1voto

Mike Kinghan Points 4567

Voir le wiki de tags Stackoverflow sur les bibliothèques statiques pour comprendre l'enchaînement avec les bibliothèques statiques, en particulier le fait que par défaut, un fichier objet libx.a(p.o) dans une bibliothèque statique est extraite et liée à un programme uniquement si l'éditeur de liens besoins il.

Si le linker a besoin de lier un membre d'archive libx.a(p.o) afin de résoudre une référence antérieure à un symbole foo qui est défini dans ce fichier d'objets, alors la définition de tout autre symbole bar qui est également défini dans libx.a(p.o) est également lié au programme - car il fait partie de ce fichier objet - que ce soit bar est référencé par le programme ou non.

Donc, si vous définissez g_register_derive dans le fichier source p.cpp qui est compilé à p.o et archivé en tant que libx.a(p.o) et votre application doit être liée à libx.a(p.o) pour toute raison alors par défaut 1 g_register_derive devient défini dans votre programme.

Si vous déplacez la définition de g_register_derive à q.cpp qui est compilé et archivé en tant que libx.a(q.o) et votre application fait no doivent être liés libx.a(q.o) pour quelque raison que ce soit, alors g_register_derive n'est pas défini dans votre programme.


[1] Avec des options de compilation et d'édition de liens autres que celles par défaut, vous pouvez supprimer des définitions de non utilisé les symboles de votre programme. Voir Comment supprimer les symboles C/C++ inutilisés avec GCC et ld ? et la réponse acceptée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X