2010-07-01 23 views
7

Esta es mi segunda publicación en este sitio en mi esfuerzo por comprender el proceso de compilación/vinculación con gcc. Cuando intento hacer un ejecutable, los símbolos deben resolverse en el momento del enlace, pero cuando intento crear una biblioteca compartida, los símbolos no se resuelven en el momento del enlace de esta biblioteca. Quizás se resolverán cuando intente hacer un ejecutable usando esta biblioteca compartida. Manos a la obra:¿Por qué los símbolos de una biblioteca compartida no se resuelven en el momento del enlace?

bash$ cat printhello.c 
#include <stdio.h> 
//#include "look.h" 

void PrintHello() 
{ 
look(); 
printf("Hello World\n"); 
} 

bash$ cat printbye.c 
#include <stdio.h> 
//#include "look.h" 

void PrintBye() 
{ 
look(); 
printf("Bye bye\n"); 
} 

bash$ cat look.h 
void look(); 

bash$ cat look.c 
#include <stdio.h> 

void look() 
{ 
printf("Looking\n"); 
} 

bash$ gcc printhello.c printbye.c 
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o: In function `_start': 
(.text+0x18): undefined reference to `main' 
/tmp/cck21S0u.o: In function `PrintHello': 
printhello.c:(.text+0x7): undefined reference to `look' 
/tmp/ccNWbCnd.o: In function `PrintBye': 
printbye.c:(.text+0x7): undefined reference to `look' 
collect2: ld returned 1 exit status 

bash$ gcc -Wall -shared -o libgreet printhello.c printbye.c 
printhello.c: In function 'PrintHello': 
printhello.c:6: warning: implicit declaration of function 'look' 
printbye.c: In function 'PrintBye': 
printbye.c:5: warning: implicit declaration of function 'look' 

Así que mi pregunta es por qué los símbolos no se resuelven cuando estoy vinculando una biblioteca compartida. Este trabajo (Resolver los símbolos de su cadena descendente) deberá realizarse cuando utilizaré esta biblioteca para hacer un ejecutable, pero eso significa que necesitamos saber de qué depende esta biblioteca cuando se utiliza esta biblioteca, pero ¿no es deseable?

Gracias, Jagrati

Respuesta

6

¿La adición de -z defs al construir la biblioteca hace lo que usted quiere? De lo contrario, consulte las páginas man de ld, existen bastantes opciones sobre el manejo de símbolos indefinidos.

0

El vinculadas tiene ninguna manera de saber, en ELF al menos, en donde los símbolos son (es decir, en que las bibliotecas). En OS X, por otro lado, debe vincular las bibliotecas de la manera que describió. Al final, es una cuestión de diseño. Uno es más flexible, el otro, más riguroso.

+0

¿Por qué se modificó esta opción? Tenga en cuenta que en OSX puede usar la opción '-flat_namespace' para que se comporte como otros sistemas operativos, por ej. Linux. – Troubadour

0

Incluso cuando crea una biblioteca compartida, debe resolver todas las dependencias.

Por lo tanto, cuando se carga una biblioteca compartida en tiempo de compilación, sabe qué otras bibliotecas compartidas cargar en el tiempo de ejecución para que pueda resolver otras dependencias.

1) Construir una compartida (mirada. < sharedLib>) de la biblioteca con la mirada()
2) Construir una compartida (hg. < sharedLib>) biblioteca con hola enlace() bye() contra la mirada. < sharedLib>
3) Aplicación de compilación con main() que enlaza con hg. < sharedlib>

En tiempo de ejecución, la aplicación cargará hg. < sharedlib> que internamente cargará la apariencia de la biblioteca compartida. < sharedlib>

2

Creo que la opción del vinculador -Bsymbolic es lo que estás buscando.

+0

No es suficiente por sí mismo. Aquí tengo una lib -Bsymbolic shared que barfs en tiempo de ejecución. – Kaz

0

Un ejecutable requiere un entry point. Pero una biblioteca compartida se puede construir sin el punto de entrada y luego el ejecutable se puede compilar con esta biblioteca compartida.

3

Parece que no entiende lo que le pidió al controlador del compilador (gcc) que hiciera en el primer comando. Como no proporcionó la opción -c (solo compilación), solicitó a gcc que compilara los dos archivos fuente y los vincule con la biblioteca estándar (libc) y el c inicio de ejecución (crt0, típicamente) para producir una ejecución programa. crt0 intenta ingresar a su programa llamando a main(), que es el símbolo indefinido que el vinculador no puede encontrar. No puede encontrarlo porque no tiene un main() en ninguno de sus archivos .c, ¿verdad?

Por lo tanto, a su pregunta real, "¿Por qué los símbolos de una biblioteca compartida no se resuelven en el momento del enlace?" La respuesta es, ¿a qué te refieres con "tiempo de enlace"? Por definición, un programa vinculado dinámicamente no se "vincula" hasta que se inicia (o tal vez ni siquiera entonces, dependiendo de su sistema.)

En un sistema Linux, puede ver de qué bibliotecas dinámicas depende un programa con el comando ldd (en Mac OS use 'otool -L'). La salida de ldd le dirá de qué bibliotecas dinámicas depende un programa, cuál se encuentra en la ruta de búsqueda de la biblioteca y cuáles no se pueden encontrar (si las hay).

Cuando se inicia el programa dinámico, el vinculador dinámico que estaba vinculado a él localiza y carga las bibliotecas dinámicas de las que depende el programa, y ​​"corrige" las referencias a los símbolos externos. Si alguno de estos falla, su programa no podrá comenzar. Uno de los símbolos anteriormente no resueltos se ha resuelto, el enlazador dinámico regresa y el tiempo de ejecución de C llamará a su función main(). (Es algo diferente en Mac OS, pero similar en efecto, la vinculación se produce después de que se inicia el programa).

Cuestiones relacionadas