web-dev-qa-db-fra.com

g ++ référence non définie bien que le symbole soit présent dans le fichier * .so

J'ai trouvé un certain nombre de questions similaires (par exemple this , that or this ), mais aucune ne m'a aidé à résoudre mon problème. J'ai un fichier * .so (du cœur de gnss-sdr ) qui, comme indiqué par:

$nm libgnss_system_parameters_dyn.so  | c++filt  |grep Gps_Eph

contient le symbole Gps_Ephemeris::Gps_Ephemeris(), qui est censé être un constructeur.

J'ai écrit du code minimal:

#include <iostream>
#include <core/system_parameters/gps_ephemeris.h>

int main(int argc,const char* argv[])
{
    Gps_Ephemeris ge;
    return 0; 
}

que je compile avec:

g++  main.cpp -std=c++0x -I some_include_path -L some_lib_path -l gnss_system_parameters_dyn`

L'éditeur de liens se plaint alors:

/tmp/ccHCvldG.o: In function `main':
main.cpp:(.text+0x33): undefined reference to `Gps_Ephemeris::Gps_Ephemeris()'
collect2: error: ld returned 1 exit status

J'ai également essayé cmake , mais la ligne qu'elle a générée était similaire à celle-ci (elle a juste ajouté -rdynamic Avant de créer un lien), et elle a quand même généré exactement la même erreur de l'éditeur de liens.

Notez que la bibliothèque et mon code minimal sont en cours de compilation avec le même compilateur (g ++ - 5), avec exactement les mêmes indicateurs et la même norme c ++ 0x.


Répondant à la réponse de Maxim Egorushkin, la ligne:

nm --demangle --defined-only --extern-only libgnss_system_parameters.so  |grep Gps_Eph

ne produit rien. Cependant, le symbole est défini dans la bibliothèque statique ( c'est-à-dire la bibliothèque * .a):

00000000000006b0 T Gps_Ephemeris::Gps_Ephemeris()
00000000000006b0 T Gps_Ephemeris::Gps_Ephemeris()

Sachant que les deux sont générés par cmake , de la manière suivante:

add_library(lib_name SHARED ${sources_etc}) #for the *.so
add_library(lib_name_2 ${sources_etc}) #for the *.a

il ne devrait pas y avoir de différence dans les symboles contenus/définis dans ces bibliothèques, non? Je n'ai rien remarqué dans la documentation de cmake sur add_library. Suis-je en train de manquer quelque chose d'évident?

36
Ash

La façon pédantiquement correcte de vérifier qu'un .so Exporte un symbole est nm --demangle --dynamic --defined-only --extern-only <lib.so> | grep <symbol>.

Sans --defined-only, Votre commande affiche également les symboles non définis.

Sans --extern-only, Il affiche également les symboles avec liaison interne qui ne sont pas disponibles pour la liaison.

Il semble que vous ayez besoin de lier une autre bibliothèque car Gps_Ephemeris::Gps_Ephermeris() n'est pas résolu en liant libgnss_system_parameters_dyn.so. Une bonne façon de commencer est la documentation et les exemples de cette bibliothèque.

26
Maxim Egorushkin

J'ai constaté dans le passé que ce type d'erreur est dû au manque de _ extern "C" { ... } bracketing dans un fichier inclus.

2
Nicole