ejecutar - instalar compilador c++ ubuntu
Obliga a GCC a notificar sobre referencias indefinidas en bibliotecas compartidas (4)
Tengo una biblioteca compartida que está vinculada a otra biblioteca compartida (de terceros). Mi biblioteca compartida se carga utilizando dlopen en mi aplicación. Todo esto funciona bien (suponiendo que los archivos están en el camino correcto, etc.).
Ahora, el problema es que ni siquiera necesito especificar un enlace contra la biblioteca compartida de terceros cuando enlace mi biblioteca. GCC lo acepta sin informar errores sobre referencias indefinidas. Entonces, la pregunta; ¿Cómo puedo obligar a GCC a notificarme sobre referencias indefinidas ?
Si cambio mi biblioteca para que sea (temporalmente) un ejecutable, obtengo referencias no definidas (cuando no estoy entregando la biblioteca al enlazador). (Funciona bien si lo especifico).
Es decir, se hace lo siguiente:
g++ -fPIC -shared -o libb.so b.o
g++ -fPIC -shared -o liba.so a.o
g++ -o a.exe a.cpp
Donde la segunda línea NO da un error y la tercera línea se queja de una referencia no definida.
Código de muestra:
ah:
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();
}
bh:
class b
{
public:
void foobar();
};
b.cpp:
#include "b.h"
void b::foobar()
{
}
Después de más investigaciones, me di cuenta de qué manera funcionan las cosas. Hay dos opciones de vinculador para manipular símbolos indefinidos de bibliotecas compartidas:
El primero es --no-undefined
. Informa los símbolos no resueltos que no se resuelven inmediatamente, en la etapa de enlace. A menos que el símbolo se encuentre en una biblioteca compartida vinculada, ya sea manualmente (con -l
switch) o automáticamente ( libgcc_s
, C ++ runtime; libc
, C runtime; ld-linux-**.so
libgcc_s
, dynamic linker utils) elegido, --no-undefined
informa como un error. Esa es la clave que el interrogador necesitaba.
Hay otra clave, --no-allow-shlib-undefined
(cuya descripción también sugiere --no-undefined
). Comprueba si se cumplen las definiciones en las bibliotecas compartidas a las que vincula su biblioteca compartida . Esta clave es de poca utilidad en el caso que se muestra en este tema, pero puede ser útil. Sin embargo, tiene sus propios obstáculos.
La página de manual proporciona algunos argumentos sobre por qué no es el valor predeterminado:
--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.
El hecho es que lo dicho anteriormente también es cierto, por ejemplo, para los sistemas Linux, donde algunas de las rutinas internas de la biblioteca compartida se implementan en ld-linux.so
, el cargador dinámico (es biblioteca ejecutable y compartida). A menos que de alguna manera lo vincules, obtendrás algo como esto:
/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''
Estas son referencias indefinidas del cargador, ld-linux.so
. Es específico de la plataforma (por ejemplo, en mi sistema, el cargador correcto es /lib64/ld-linux-x86-64.so
). Puede vincular el cargador con su biblioteca y verificar incluso las referencias engañosas que se muestran arriba:
g++ -fPIC -shared -o liba.so a.o -Wl,--no-allow-shlib-undefined /lib64/ld-linux-x86-64.so.2
No puede hacer que ld (que es lo que está ejecutando gcc) preste atención a una biblioteca que no está allí en el enlace. Puede desactivar RTLD_LAZY para obtener informes agresivos, y puede agregar una prueba de unidad que se ejecuta justo después del enlace para solucionar estos problemas.
También hay una buena discusión de esto en la wiki de Mandriva .
-Wl, - la opción del enlazador no indefinido se puede usar al compilar una biblioteca compartida, los símbolos indefinidos se mostrarán como errores del enlazador.
g ++ -shared -Wl, -soname, libmylib.so.5 -Wl, -no-undefined -o libmylib.so.1.1 mylib.o -lthirdpartylib