77 votes

Vérification facile des symboles non résolus dans les bibliothèques partagées?

Je suis en train d'écrire un assez grand C++ partagée la bibliothèque d'objets, et ont rencontré un petit problème qui rend le débogage d'une douleur:

Si je définis une fonction/méthode dans un fichier d'en-tête, et oublier de créer un stub pour elle (en cours de développement), depuis que je suis bâtiment comme un objet partagé bibliothèque plutôt que d'un exécutable, pas d'erreurs apparaissent au moment de la compilation de me dire que j'ai oublié de la mettre en fonction. La seule façon que je trouve quelque chose est mauvais, c'est au moment de l'exécution, lorsque finalement une demande de liaison à l'encontre de cette bibliothèque tombe sur un "undefined symbol' erreur.

Je suis à la recherche d'un moyen facile de vérifier si j'ai tous les symboles dont j'ai besoin au moment de la compilation, peut-être quelque chose que je peux ajouter à mon Makefile.

Une solution je suis venu avec est de lancer la compilation de la bibliothèque par le biais nm -C -U pour obtenir un demangled liste de tous les indéfini références. Ce problème est également livré avec la liste de toutes les références qui sont dans d'autres bibliothèques, comme la GLibC, ce qui bien sûr va être liées avec cette bibliothèque lors de l'application finale est mis en place. Il serait possible d'utiliser la sortie d' nm de grep à travers tous mes fichiers d'en-tête et de voir si l'un des noms correspondant.. mais cela semble fou. Ce n'est sûrement pas rare de problème et il y a une meilleure façon de le résoudre?

88voto

R Samuel Klatchko Points 44549

Découvrez le linker option "-z defs" / "--no-undefined". Lors de la création d'un objet partagé, il fera le lien à l'échec si il y a des symboles non résolus.

Si vous utilisez gcc pour appeler l'éditeur de liens, vous allez utiliser le compilateur-Wl option pour passer à l'option de l'éditeur de liens:

gcc -shared ... -Wl,-z,defs

Considérez, par exemple, le fichier suivant:

#include <stdio.h>

void forgot_to_define(FILE *fp);

void doit(const char *filename)
{
    FILE *fp = fopen(filename, "r");
    if (fp != NULL)
    {
        forgot_to_define(fp);
        fclose(fp);
    }
}

Maintenant, si vous créez un objet partagé, il va réussir:

> gcc -shared -fPIC -o libsilly.so silly.c && echo succeeded || echo failed
succeeded

Mais si vous ajoutez -z defs, le lien va échouer et vous dire au sujet de votre symbole manquant:

> gcc -shared -fPIC -o libsilly.so silly.c -Wl,-z,defs && echo succeeded || echo failed
/tmp/cccIwwbn.o: In function `doit':
silly.c:(.text+0x2c): undefined reference to `forgot_to_define'
collect2: ld returned 1 exit status
failed

15voto

Employed Russian Points 50479

Sous Linux (que vous utilisez apparemment) ldd -r a.out devrait vous donner exactement la réponse que vous recherchez.

UPDATE: un moyen simple de créer a.out contre lequel vérifier:

  echo "int main() { return 0; }" | g++ -xc++ - ./libMySharedLib.so
 ldd -r ./a.out
 

8voto

Stefano Borini Points 36904

Qu'en est-il d'une suite de tests? Vous créez des exécutables factices qui renvoient aux symboles dont vous avez besoin. Si la liaison échoue, cela signifie que l'interface de votre bibliothèque est incomplète.

3voto

Diego Sevilla Points 17274

J'ai eu le même problème une fois. J'ai été l'élaboration d'un modèle de composant en C++, et, bien sûr, les composants doivent se charger dynamiquement lors de l'exécution. Trois solutions me viennent à l'esprit, c'étaient ceux que j'ai appliqué:

  1. Prenez le temps de définir un système de construction qui est en mesure de compiler statiquement. Vous allez perdre un peu de temps d'ingénierie, mais il vous fera économiser beaucoup de temps attraper ces satanés des erreurs d'exécution.
  2. Groupe de vos fonctions bien connues et bien comprises sections, de sorte que vous pouvez le groupe de fonctions/talons pour s'assurer que chaque fonction correspondante a son talon. Si vous prenez le temps sur la documentation de bien, vous pouvez peut-être écrire un script qui vérifie les définitions (via, par exemple, ses commentaires doxygen) et cochez la case correspondante .fichier cpp.
  3. Faire plusieurs test exécutables de charger le même ensemble de bibliothèques et de spécifier le RTLD_NOW drapeau de dlopen (si vous êtes sous *NIX). Ils signaleront les symboles manquants.

Espérons que cela aide.

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