J'ai une bibliothèque partagée liée à une autre bibliothèque partagée (tierce). Ma bibliothèque partagée est ensuite chargée à l'aide de dlopen dans mon application. Tout cela fonctionne bien (en supposant que les fichiers sont dans le bon chemin, etc.).
Maintenant, le problème est que je n'ai même pas besoin de spécifier un lien avec la bibliothèque partagée tierce lorsque je lie ma bibliothèque. GCC l'accepte sans signaler d'erreurs concernant les références non définies. Donc, la question; comment puis-je forcer GCC à me notifier les références non définies?
Si je change ma bibliothèque pour qu'elle soit (temporairement) un exécutable, j'obtiens des références non définies (lorsque je ne fournis pas la bibliothèque à l'éditeur de liens). (Fonctionne bien si je le spécifie.)
C'est-à-dire que ce qui suit est effectué:
g++ -fPIC -shared -o libb.so b.o
g++ -fPIC -shared -o liba.so a.o
g++ -o a.exe a.cpp
Où la deuxième ligne ne donne PAS d'erreur et la troisième ligne se plaint d'une référence non définie.
Exemple de code:
a.h:
class a
{
public:
void foobar();
};
a.cpp:
#include "a.h"
#include "b.h"
void a::foobar()
{
b myB;
myB.foobar();
}
int main()
{
a myA; myA.foobar();
}
b.h:
class b
{
public:
void foobar();
};
b.cpp:
#include "b.h"
void b::foobar()
{
}
- Wl, - no-undefined L'option de l'éditeur de liens peut être utilisée lors de la construction d'une bibliothèque partagée, les symboles non définis seront affichés comme des erreurs de l'éditeur de liens.
g ++ -shared -Wl, -soname, libmylib.so.5 -Wl, - no-undefined -o libmylib.so.1.1 mylib.o -lthirdpartylib
Après plus de recherches, j'ai réalisé comment les choses fonctionnaient. Il existe deux options de l'éditeur de liens pour manipuler les symboles non définis des bibliothèques partagées:
Le premier est --no-undefined
. Il signale les symboles non résolus qui ne sont pas résolus immédiatement, au stade de la liaison. Sauf si le symbole se trouve dans une bibliothèque partagée liée, soit manuellement (avec -l
switch) ou automatiquement (libgcc_s
, Runtime C++; libc
, runtime C; ld-linux-**.so
, utilitaires de l'éditeur de liens dynamiques) sélectionnés, --no-undefined
le signale comme une erreur. C'est la clé dont l'intervenant avait besoin.
Il y a une autre clé, --no-allow-shlib-undefined
(dont la description suggère également --no-undefined
). Il vérifie si les définitions dans les bibliothèques partagées auxquelles vous liez votre bibliothèque partagée sont satisfaites. Cette clé est peu utile dans le cas présenté dans cette rubrique, mais elle peut être utile. Cependant, il a ses propres obstacles.
La page de manuel explique pourquoi ce n'est pas le cas par défaut:
--allow-shlib-undefined
--no-allow-shlib-undefined
Allows (the default) or disallows undefined symbols in shared
libraries (It is meant, in shared libraries _linked_against_, not the
one we're creating!--Pavel Shved). This switch is similar to --no-un-
defined except that it determines the behaviour when the undefined
symbols are in a shared library rather than a regular object file. It
does not affect how undefined symbols in regular object files are
handled.
The reason that --allow-shlib-undefined is the default is that the
shared library being specified at link time may not be the same as
the one that is available at load time, so the symbols might actually
be resolvable at load time. Plus there are some systems, (eg BeOS)
where undefined symbols in shared libraries is normal. (The kernel
patches them at load time to select which function is most appropri-
ate for the current architecture. This is used for example to dynam-
ically select an appropriate memset function). Apparently it is also
normal for HPPA shared libraries to have undefined symbols.
Le fait est que ce qui est dit ci-dessus est également vrai, par exemple, pour les systèmes Linux, où certaines des routines internes de la bibliothèque partagée sont implémentées dans ld-linux.so
, le chargeur dynamique (c'est à la fois une bibliothèque exécutable et partagée). À moins que vous ne le liez d'une manière ou d'une autre, vous obtiendrez quelque chose comme ceci:
/lib64/libc.so.6: undefined reference to `_dl_argv@GLIBC_PRIVATE'
/lib64/libc.so.6: undefined reference to `_rtld_global_ro@GLIBC_PRIVATE'
/usr/lib64/gcc/x86_64-suse-linux/4.3/libstdc++.so: undefined reference to `__tls_get_addr@GLIBC_2.3'
/lib64/libc.so.6: undefined reference to `_rtld_global@GLIBC_PRIVATE'
/lib64/libc.so.6: undefined reference to `__libc_enable_secure@GLIBC_PRIVATE'
Ce sont des références indéfinies du chargeur, ld-linux.so
. Il est spécifique à la plate-forme (par exemple, sur mon système, le chargeur correct est /lib64/ld-linux-x86-64.so
). Vous pouvez lier le chargeur à votre bibliothèque et vérifier même les références délicates indiquées ci-dessus:
g++ -fPIC -shared -o liba.so a.o -Wl,--no-allow-shlib-undefined /lib64/ld-linux-x86-64.so.2
Vous ne pouvez pas faire ld (qui est ce que gcc exécute) faire attention à une bibliothèque qui n'est pas là dans le lien. Vous pouvez désactiver RTLD_LAZY pour obtenir des rapports agressifs, et vous pouvez ajouter un test unitaire qui s'exécute juste après le lien juste pour éliminer ces problèmes.