Domanda Comportamento del linker molto strano


Questo è strano perché sono stato in grado di ottenere l'errore in basso per andare via rimuovendo il riferimento a libm.

gcc -o example example.o -Wl -L/home/kensey/cdev/lib -L/usr/lib/x86_64-linux-gnu   -lmysqlclient -lpthread -lz -L/usr/lib/x86_64-linux-gnu -lm -lrt -ldl -lcdev -L/home/kensey/www.tools/gplot-lib -lgplot -L/home/kensey/www.tools/gd1_3ret -lgd -lxml2 -lcurl
/usr/bin/ld: /home/kensey/www.tools/gplot-lib/libgplot.a(set.o): undefined reference to symbol 'floor@@GLIBC_2.2.5'
/usr/bin/ld: note: 'floor@@GLIBC_2.2.5' is defined in DSO /usr/lib/x86_64-linux-gnu/libm.so so try adding it to the linker command line
/usr/lib/x86_64-linux-gnu/libm.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status

Quindi, se rimuovo il -lm parte del comando, non ho ricevuto l'errore. Tuttavia, mi chiedo se qualcuno sa perché rimuovere un riferimento a una libreria che è necessario risolverebbe questo problema. Come fa il linker a sapere in quale libreria cercare? Inoltre, c'è un modo per interrogare un eseguibile costruito e dire "quale libreria hai risolto con riferimento a" floor "? ovviamente, c'è qualcosa che non capisco e che mi infastidisce ...


44
2018-03-29 22:33


origine


risposte:


La spiegazione di ciò che sta accadendo è molto semplice:

  1. Il tuo libgplot.a dipende da libm.so, ancora l'ordine di -lm e -lgplot sulla linea di collegamento è sbagliato. L'ordine delle librerie sulla linea di collegamento fa  importa. In generale, le librerie di sistema (-lpthread, -lm, -lrt, -ldl) dovrebbero Seguire tutto il resto sulla linea di collegamento.

  2. Quando rimuovi -lm dalla linea di collegamento, libm.so.6 è ancora inserito nel link da qualche altra libreria che appare in seguito sulla linea di collegamento (libgd, libxml2 o libcurl) perché quella libreria dipende da libm.so.6. Ma ora libm.so.6 è nella posizione corretta sulla linea di collegamento e quindi tutto funziona.

se metto -lm alla fine del comando link, elencandolo come l'ultima libreria, non ottengo l'errore.

Ciò conferma la spiegazione sopra.


83
2018-04-23 04:01



Ho risolto lo stesso problema con export LDFLAGS="$LDFLAGS -lm"


8
2018-04-25 10:28



Forse, i percorsi di ricerca della libreria (/ usr / local / lib / o / usr / lib /, ...) non contengono la libm a 64 bit, quindi gcc non può individuarlo se si specifica con l bandiera. Se si specifica solo la directory, sembra che possa trovare quella giusta. Quindi puoi provare:

LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu

e usare -lm


6
2018-03-29 22:44



Difficile da dire. Perché ci sono directory di librerie personalizzate nella riga di comando è concepibile che -lm collega una versione alternativa incompatibile. Senza -lm il linker potrebbe inserire un'altra versione di esso perché è necessaria da una delle librerie collegate.

Assicurarsi strace entrambe le invocazioni e vedere dove libm.so viene da entrambi i casi.

BTW, -Wl interruttore sembra non fare nulla e -L/usr/lib/x86_64-linux-gnu è menzionato due volte.


3
2018-03-29 22:42



Solo per aggiungere all'elenco delle risposte, http://fedoraproject.org/wiki/UnderstandingDSOLinkChange È informativo. Non è rilevante per la domanda posta sopra, ma la spiegazione si riferisce al messaggio di errore /usr/bin/ld: note: 'some_reference' is defined in DSO some.so so try adding it to the linker command line


2
2018-05-20 09:27



Una spiegazione poteva essere:

Forse c'è una funzione debolmente legata foo definito al di fuori di libm che viene sostituito da una versione fortemente collegata di foo definito all'interno di libm, ed è questa versione fortemente collegata che chiama la funzione non definita.

Questo spiegherebbe come l'aggiunta di una libreria può causare un errore di funzione indefinito.


1
2018-03-29 22:51



Ho appena incontrato un problema simile; Ricordo che l'ordine delle biblioteche non aveva importanza (almeno non nei casi in cui ho lavorato) in passato per gcc. In questa domanda qui qualcuno ha notato che il comportamento sembra essere cambiato tra 4.4 e 4.5.

Nel mio caso, mi sono sbarazzato del messaggio di errore facendo il collegamento a:

 g++ -Wl,--copy-dt-needed-entries [options] [libraries] [object files] -o executable-file

1
2018-06-03 20:01



Usa questo:

administrator@administrator-Veriton-M200-H81:~/ishan$ gcc polyscanline1.cpp -lglut -lGLU -lGL -lm

-1
2018-02-25 06:00