2012-06-20 13 views
6

Ho cercato di compilare il mio progetto e sto ricevendo errori undefined reference. ad es .:Linked non riesce a trovare i simboli, ma le librerie sono leggere ei simboli esistono

installertest.cpp:(.text+0x9d1): undefined reference to `XmlRpcValue::makeArray()' 
... 
installertest.cpp:(.text+0xede): undefined reference to `dbcancel' 
installertest.cpp:(.text+0xefd): undefined reference to `dbfcmd' 
installertest.cpp:(.text+0xf0f): undefined reference to `dbsqlexec' 
installertest.cpp:(.text+0xf2d): undefined reference to `SHA1_Init' 
... 

My-riga di comando è:

g++ -o installertest \ 
    -lsybdb \ 
    -lxmlrpc \ 
    -lxmlrpc_cpp \ 
    -lxmlrpc_xmlparse \ 
    -lxmlrpc_xmltok \ 
    -lxmlrpc_util \ 
    -lxmlrpc++ \ 
    -lxmlrpc_server_cgi \ 
    -lssl \ 
    -std=c++0x \ 
    ContractData.o installertest.o 

objdump -T dimostra che i simboli sono nel file .so. ad es .:

libsybdb.so: 
... 
0000000000011c30 g DF .text 0000000000000083 Base  dbcancel 
... 

/usr/lib/libxmlrpc_cpp.so: 
... 
0000000000002e78 g DF .text 0000000000000092 Base  _ZN11XmlRpcValue9makeArrayEv 
... 

strace dimostra che i file di libreria vengono aperti e letti dal linker:

... 
[pid 5019] stat("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libsybdb.so", {st_mode=S_IFREG|0644, st_size=421608, ...}) = 0 
[pid 5019] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libsybdb.so", O_RDONLY) = 7 
[pid 5019] fcntl(7, F_GETFD)   = 0 
[pid 5019] fcntl(7, F_SETFD, FD_CLOEXEC) = 0 
[pid 5019] fstat(7, {st_mode=S_IFREG|0644, st_size=421608, ...}) = 0 
[pid 5019] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b16c200c000 
[pid 5019] lseek(7, 0, SEEK_SET)  = 0 
[pid 5019] read(7, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\0\0\0\0\0\0"..., 4096) = 4096 
... 
[pid 5019] stat("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../lib/libxmlrpc.so", {st_mode=S_IFREG|0644, st_size=80936, ...}) = 0 
[pid 5019] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../lib/libxmlrpc.so", O_RDONLY) = 8 
[pid 5019] fcntl(8, F_GETFD)   = 0 
[pid 5019] fcntl(8, F_SETFD, FD_CLOEXEC) = 0 
[pid 5019] fstat(8, {st_mode=S_IFREG|0644, st_size=80936, ...}) = 0 
[pid 5019] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b16c200d000 
[pid 5019] lseek(8, 0, SEEK_SET)  = 0 
[pid 5019] read(8, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300?\0\0\0\0\0\0"..., 4096) = 4096 
... 

Tutti i file coinvolti sono mirati al x86-64 e l'intestazione per il C librerie sono extern "C" . Ho provato tutto quello che riesco a pensare e ancora non collegherà.

Ho anche provato a rimuovere tutto il codice C++ 11 e la compilazione senza l'interruttore della riga di comando, ancora nulla.

Il mio sistema è Ubuntu Precise (12.04) a 64 bit utilizzandog ++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 se questo aiuta. Tutti i pacchetti sono stati installati dal gestore pacchetti e vengono installati i pacchetti di sviluppo.

Edit (2017/05/30): contrassegnato come duplicato di https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc
Altra domanda chiede perché ordine degli argomenti è importante. Non si sapeva che l'ordine degli argomenti fosse un problema quando veniva posta una domanda.
Inoltre, la domanda precedente non contiene alcuna espansione utile, mentre questa domanda mostra il problema in questione.
La domanda precedente può essere vista come un'utile espansione sulla risposta a questa, ma non una duplicazione.

+0

Ciao, Ben. Potrebbe per favore mostrarmi come usare lo strace per verificare il processo. La mia difficoltà principale riguarda come ottenere il PID, poiché il processo di compilazione muore molto rapidamente. Io uso solo la ps aux | grep per ottenere il PID, ma il processo è già morto. – William

+0

@XingWang, nessun problema. Devi semplicemente anteporre "strace -f -e trace = all" alla tua riga di comando. A seconda del sistema, potrebbe essere necessario aggiungere "sudo". Quindi, dal mio esempio: "strace -f -e trace = all g ++ -o installertest ContractData.o installertest.o" ... –

+0

Possibile duplicato di [Perché l'ordine in cui le librerie sono collegate a volte causa errori in GCC?] (https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc) –

risposta

9

È necessario inserire le flag del linker delle librerie dopo i file oggetto. Così, invece di

g++ -o installertest \ 
-lsybdb \ 
-lxmlrpc \ 
-lxmlrpc_cpp \ 
-lxmlrpc_xmlparse \ 
-lxmlrpc_xmltok \ 
-lxmlrpc_util \ 
-lxmlrpc++ \ 
-lxmlrpc_server_cgi \ 
-lssl \ 
-std=c++0x \ 
ContractData.o installertest.o 

uso

g++ -o installertest \ 
ContractData.o installertest.o \ 
-lsybdb \ 
-lxmlrpc \ 
-lxmlrpc_cpp \ 
-lxmlrpc_xmlparse \ 
-lxmlrpc_xmltok \ 
-lxmlrpc_util \ 
-lxmlrpc++ \ 
-lxmlrpc_server_cgi \ 
-lssl \ 
-std=c++0x 
+0

Appena provato correttamente, ha funzionato. Veramente!? Non posso credere che fosse così semplice. –

+1

Per chiunque altro venga a conoscenza di questo problema, ecco il ragionamento. Sembra che gcc ora invii il flag linker --as - necessario per ld. Questo ha l'effetto di scartare qualsiasi libreria specificata che non ha simboli richiesti per il collegamento. Nella prima istanza, tutte le librerie venivano scartate perché non c'erano simboli non risolti, quindi nella fase di collegamento i simboli non potevano essere trovati. Nella seconda istanza, ld aveva raccolto l'elenco dei simboli non risolti e li ha trovati nelle librerie specificate e quindi li ha mantenuti quando si trattava della fase di collegamento effettiva. –