Referencia indefinida a ‘pthread_create’: orden de las opciones del comando del enlazador (¿bibliotecas antes / después de los archivos del objeto?)

Cuando bash comstackr eso, recibo un error en particular. Pero no es posible porque utilizo la bandera correcta. En server.c está la biblioteca pthread.h . Entonces, ¿cómo puedo resolver mi problema de vinculación? Estoy usando Linux (Ubuntu).

 make gcc -c -Wall -Wunused -ansi -pedantic -ggdb -o Server1.o Server.c gcc -c -Wall -Wunused -ansi -pedantic -ggdb Util.c gcc -o Server1.exe -Wall -Wunused -ansi -pedantic -ggdb -lpthread -lm Server1.o Util.o Server1.o: In function `main': /home/ruggero/ruggero_fine/Server.c:1002: undefined reference to `pthread_create' collect2: ld returned 1 exit status make: *** [Server1.exe] Errore 1 

Lista de bibliotecas después de los archivos de objeto

Al vincular solo archivos de objetos y bibliotecas, enumere las bibliotecas después de los archivos de objeto:

 gcc -o Server1.exe -Wall -Wunused -ansi -pedantic -ggdb Server1.o Util.o -lpthread -lm 

Cuando el comando de enlace incluye archivos de origen, enumere los archivos de origen y los archivos de objeto (si los hay) antes de las bibliotecas. Las opciones -l vienen al final de la línea de comando, por lo tanto. Las opciones -L relevantes que especifican dónde se encuentra una biblioteca deben aparecer antes de la opción -l especifica la biblioteca.

La pregunta subsidiaria es:

¿Por qué funciona?

Cuando el comstackdor de C invoca el enlazador, le dice al vinculador que crt0.o algunos archivos de objetos del sistema con nombres como crt0.o , y le dice que busque un símbolo main (o posiblemente _main() , dependiendo de las convenciones de nomenclatura locales). También proporciona los archivos de objeto y las bibliotecas en el orden que especificó en la línea de comando. Cuando se encuentra con un archivo objeto, el enlazador toma nota de las definiciones que proporciona y las referencias insatisfechas que hace. Cuando se encuentra con una biblioteca, escanea la biblioteca para ver si puede satisfacer cualquier referencia insatisfecha. Si la biblioteca puede suministrar referencias que todavía no estén satisfechas, entonces incluye (las partes relevantes de) la biblioteca ‘en el ejecutable’. Para una biblioteca compartida, el vinculador garantiza que la biblioteca se cargará en tiempo de ejecución. Para una biblioteca estática, el enlazador incluye los archivos objeto de la biblioteca que satisfacen al menos una referencia, volviendo a escanear hasta que no haya más referencias que puedan cumplirse. Si la biblioteca no cumple ninguna referencia, se ignora. Cuando el proceso está completo, si todavía hay referencias insatisfechas, aparece el mensaje de error.

Entonces, en su situación hipotética, usted había -lpthread antes de Server1.o o Util.o Como -lpthread no proporciona una función main y ese fue el único símbolo relevante insatisfecho, se ignoró. La biblioteca de matemática, -lm también puede haber sido ignorada, o puede ser un trozo vacío para mantener el código diseñado para otros sistemas donde la biblioteca de matemáticas está separada de la biblioteca principal de C. Luego, el vinculador leyó los archivos de objetos y encontró la referencia a pthread_create() . Cuando escaneó la biblioteca C -lc ( libc.so ) después, encontró símbolos para satisfacer todo excepto pthread_create .

Cuando las bibliotecas se enumeran después de los archivos objeto, el vinculador sabía que necesitaba pthread_create cuando escaneaba -lpthread y se aseguraba de que la biblioteca compartida se cargara en tiempo de ejecución.

GNU ld y la opción --as-needed

La discusión anterior es esencialmente neutral de plataforma. Si sigue la regla ‘bibliotecas después de los archivos de objeto’, su línea de vinculador tiene la mayor posibilidad de funcionar correctamente en todas las plataformas.

Si está en un sistema que usa el paquete binutils GNU, y el comando GNU ld en particular, puede encontrar un comportamiento diferente.

El manual de Sourceware (que es donde se te redirige si pruebas http://www.gnu.org/software/binutils/manuals ) incluye la información:

--as-needed
--no-as-needed
Esta opción afecta a las tags ELF DT_NEEDED para bibliotecas dinámicas mencionadas en la línea de comando después de la opción --as-needed . Normalmente, el enlazador agregará una etiqueta DT_NEEDED para cada biblioteca dinámica mencionada en la línea de comandos, independientemente de si la biblioteca es realmente necesaria o no. --as-needed hace que una etiqueta DT_NEEDED solo se emita para una biblioteca que en ese punto del enlace satisfaga una referencia de símbolo indefinido no débil de un archivo de objeto normal o, si la biblioteca no se encuentra en las listas DT_NEEDED de otra bibliotecas, una referencia de símbolo indefinido no débil de otra biblioteca dinámica. Los archivos de objetos o las bibliotecas que aparecen en la línea de comandos después de la biblioteca en cuestión no afectan si la biblioteca se ve si es necesaria. Esto es similar a las reglas para la extracción de archivos de objeto de los archivos. --no-as-needed restaura el comportamiento predeterminado.

Parece que diferentes versiones de diferentes sistemas usan diferentes valores para la opción as-needed . Si bien el comportamiento “no --no-as-needed es conveniente porque le permite ordenar bibliotecas y archivos de objetos en más o menos orden en su línea de comandos, también significa que todas las bibliotecas enumeradas en la línea de comandos se cargan en tiempo de ejecución , incluso si no hay símbolos realmente utilizados en la biblioteca (por lo tanto, si no es --no-as-needed es equivalente a un --whether-needed-or-not hipotético de ” --whether-needed-or-not ). Usar la opción --as-needed es el comportamiento clásico y portátil.

Corre el rumor de que algunas distribuciones de Linux cambiaron el comportamiento predeterminado en sus sistemas de --no-as-needed a --as-needed en algún momento de los últimos 5 años (la primera mitad de la segunda década del tercer milenio, motivo de discusión). Puede encontrar pruebas en apoyo de este rumor en una serie de preguntas sobre SO.

Use -pthread al comstackr. Pruébalo y resolverás tu problema