Question

Je suis en train d'écrire une bibliothèque d'objets partagés C ++ assez volumineuse et j'ai rencontré un petit problème qui rend le débogage très pénible:

Si je définis une fonction / méthode dans un fichier d'en-tête et oublie de créer un stub pour celle-ci (pendant le développement), car je construis en tant que bibliothèque d'objets partagés plutôt qu'en tant qu'exécutable, aucune erreur ne survient lors de la compilation moi j'ai oublié de mettre en œuvre cette fonction. La seule façon pour moi de découvrir que quelque chose ne va pas, c'est au moment de l'exécution, lorsqu'une application qui fait le lien avec cette bibliothèque tombe alors avec une erreur 'symbole indéfini'.

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

Une solution que j'ai trouvée consiste à exécuter la bibliothèque compilée via nm -C -U pour obtenir une liste démêlée de toutes les références non définies. Le problème est que cela donne également la liste de toutes les références qui se trouvent dans d’autres bibliothèques, telles que GLibC, qui seront bien sûr liées à cette bibliothèque lors du montage de l’application finale. Il serait possible d'utiliser la sortie de nm pour grep à travers tous mes fichiers d'en-tête et voir si l'un des noms correspond à .. mais cela semble insensé. Ce n'est certainement pas un problème rare et il existe un meilleur moyen de le résoudre?

Était-ce utile?

La solution

Vérifiez l'option de l'éditeur de liens -z defs / - no-undefined . Lors de la création d'un objet partagé, le lien échouera s'il y a des symboles non résolus.

Si vous utilisez gcc pour appeler l'éditeur de liens, vous utiliserez l'option -Wl du compilateur pour transmettre l'option à l'éditeur de liens:

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

A titre d'exemple, considérons 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 construisez cela dans un objet partagé, cela réussira:

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

Mais si vous ajoutez -z defs , le lien échouera et vous indiquera 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

Autres conseils

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

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

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

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.

J'ai eu le même problème une fois. Je développais un modèle de composant en C ++ et, bien entendu, les composants devaient se charger de manière dynamique au moment de l'exécution. Trois solutions me viennent à l’esprit, c’est celles que j’ai appliquées:

  1. Prenez le temps de définir un système de compilation capable de compiler de manière statique. Vous perdrez un peu de temps à l’ingénierie, mais vous épargnerez beaucoup de temps à attraper ces ennuyeuses erreurs d’exécution.
  2. Regroupez vos fonctions dans des sections bien connues et bien comprises afin de pouvoir grouper des fonctions / stubs afin de vous assurer que chaque fonction correspondante a son stub. Si vous prenez le temps de bien la documenter, vous pouvez peut-être écrire un script qui vérifie les définitions (via, par exemple, ses commentaires doxygen) et recherchez le fichier .cpp correspondant.
  3. Faites plusieurs exécutables de test qui chargent le même ensemble de bibliothèques et spécifiez l'indicateur RTLD_NOW sur dlopen (si vous êtes sous * NIX). Ils signaleront les symboles manquants.

L’espoir que cela aide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top