2012-06-20 45 views
6

我一直在嘗試編譯我的項目,並且得到undefined reference錯誤。例如:鏈接找不到符號,但庫被讀取並且符號存在

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' 
... 

我的命令行是:

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顯示這些符號在.so文件。例如:

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

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

strace顯示,庫文件被打開,並通過鏈接閱讀:

... 
[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 
... 

參與是針對所有文件X86-64和頭爲C庫extern "C" 。我已經嘗試了所有我能想到的事情,但它仍然無法鏈接。

我甚至嘗試刪除所有C++ 11代碼並在沒有命令行開關的情況下編譯,仍然沒有任何結果。

我的系統是Ubuntu的精確(12.04)64位使用克++(Ubuntu的/ Linaro的4.6.3-1ubuntu5)4.6.3沒有什麼幫助。所有軟件包都是從軟件包管理器安裝的,並且安裝了開發包。

編輯(2017年5月30日)註明爲https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc
其他問題重複問爲什麼的參數順序很重要。當提出問題時,論據順序不被認爲是一個問題。
另外,上一個問題不包含任何有用的擴展,而這個問題顯示了手頭的問題。
上一個問題可能被看作是對這個答案的有益擴展,但不是重複。

+0

嗨,本。你能告訴我如何使用strace來檢查過程。我的主要困難是如何獲得PID,因爲編譯過程非常快。我只使用ps aux | grep來獲得PID,但這個過程已經死了。 – William

+0

@XingWang,沒問題。你只需要在命令行中加上「strace -f -e trace = all」即可。根據您的系統,您可能還需要添加「sudo」。所以,從我的例子中:「strace -f -e trace = all g ++ -o installertest ContractData.o installertest.o」... –

+0

[爲什麼庫鏈接的順序有時會導致GCC錯誤?] (https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc) –

回答

9

您必須將庫的鏈接器標記放在之後的目標文件中。所以,與其

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 

使用

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

剛試過,工作。真!?簡直不敢相信。 –

+1

對於這個問題的任何其他人,這是推理。看來gcc現在會將連接器標誌 - 需要發送給ld。這具有放棄任何不具有鏈接所需的符號的指定庫的效果。 在第一種情況下,所有庫都被丟棄,因爲沒有未解決的符號,因此在鏈接階段,找不到符號。 在第二個實例中,ld收集了未解析符號的列表,然後在指定的庫中找到它們,並在實際鏈接階段保留它們。 –