2012-06-20 20 views
6

Tôi đã cố gắng biên dịch dự án của mình và tôi nhận được lỗi undefined reference. Eg .:Liên kết không thể tìm thấy biểu tượng, nhưng các thư viện được đọc và ký hiệu tồn tại

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 dòng lệnh là:

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 cho thấy những biểu tượng là trong file .so. Eg .:

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

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

strace cho thấy rằng các tập tin thư viện đang được mở ra và đọc bởi mối liên kết:

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

Tất cả các file liên quan được nhắm mục tiêu đến x86-64 và tiêu đề cho C thư viện là extern "C" . Tôi đã thử mọi thứ tôi có thể nghĩ và nó vẫn không liên kết.

Tôi thậm chí đã thử xóa tất cả mã C++ 11 và biên dịch mà không cần chuyển đổi dòng lệnh, vẫn không có gì.

hệ thống của tôi là Ubuntu Precise (12.04) 64-bit sử dụng g ++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 nếu giúp. Tất cả các gói đã được cài đặt từ trình quản lý gói và các gói phát triển được cài đặt.

Chỉnh sửa (2017/05/30): đánh dấu như bản sao của https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc
câu hỏi khác hỏi tại sao trật tự của các đối số là quan trọng. Thứ tự đối số không được biết là một vấn đề khi câu hỏi được hỏi.
Ngoài ra, câu hỏi trước không chứa bất kỳ mở rộng hữu ích nào, trong khi câu hỏi này cho thấy sự cố trong tầm tay.
Câu hỏi trước có thể được xem là mở rộng hữu ích về câu trả lời cho câu trả lời này, nhưng không phải là một sự trùng lặp.

+0

Hi, Ben. Bạn có thể vui lòng chỉ cho tôi cách sử dụng strace để kiểm tra quá trình. Khó khăn chính của tôi là làm thế nào để có được PID, khi quá trình biên dịch chết rất nhanh. Tôi chỉ sử dụng ps aux | grep để lấy PID, nhưng quá trình này đã chết. – William

+0

@XingWang, không sao cả. Bạn chỉ cần thêm "strace -f -e trace = all" vào dòng lệnh của mình. Tùy thuộc vào hệ thống của bạn, bạn cũng có thể cần phải thêm "sudo". Vì vậy, từ ví dụ của tôi: "strace -f -e trace = tất cả g ++ -o installertest ContractData.o installertest.o" ... –

+0

Có thể trùng lặp [Tại sao thứ tự các thư viện được liên kết đôi khi gây ra lỗi trong GCC?] (https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc) –

Trả lời

9

Bạn phải đặt cờ liên kết của thư viện sau các tệp đối tượng. Vì vậy, thay vì

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 

sử dụng

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

Vừa thử đúng cách, hiệu quả. Có thật không!? Không thể tin nó đơn giản như thế. –

+1

Đối với bất kỳ ai khác gặp phải vấn đề này, đây là lý do. Có vẻ như gcc bây giờ gửi cờ liên kết - rất cần thiết cho ld. Điều này có tác dụng loại bỏ bất kỳ thư viện được chỉ định nào không có biểu tượng được yêu cầu để liên kết. Trong trường hợp đầu tiên, tất cả các thư viện đã bị loại bỏ là nguyên nhân không có biểu tượng chưa được giải quyết trong giai đoạn liên kết, các ký hiệu không thể tìm thấy. Trong trường hợp thứ hai, ld đã thu thập danh sách các ký hiệu chưa được giải quyết và sau đó tìm thấy chúng trong các thư viện được chỉ định và do đó giữ chúng khi nó đến giai đoạn liên kết thực tế. –