libpthread.so.0: lỗi thêm ký hiệu: DSO bị thiếu trong dòng lệnh


205

Khi tôi biên dịch openvswitch-1.5.0, tôi đã gặp phải lỗi biên dịch sau:

 gcc -Wstrict-prototypes -Wall -Wno-sign-compare -Wpointer-arith
     -Wdeclaration-after-statement -Wformat-security -Wswitch-enum -Wunused-parameter -Wstrict-aliasing -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-field-initializers -Wno-override-init  -g -O2 -export-dynamic ***-lpthread***  -o utilities/ovs-dpctl utilities/ovs-dpctl.o lib/libopenvswitch.a
 /home/jyyoo/src/dpdk/build/lib/librte_eal.a
 /home/jyyoo/src/dpdk/build/lib/libethdev.a
 /home/jyyoo/src/dpdk/build/lib/librte_cmdline.a
 /home/jyyoo/src/dpdk/build/lib/librte_hash.a
 /home/jyyoo/src/dpdk/build/lib/librte_lpm.a
 /home/jyyoo/src/dpdk/build/lib/librte_mbuf.a
 /home/jyyoo/src/dpdk/build/lib/librte_ring.a
 /home/jyyoo/src/dpdk/build/lib/librte_mempool.a
 /home/jyyoo/src/dpdk/build/lib/librte_malloc.a -lrt -lm 
     /usr/bin/ld: /home/jyyoo/src/dpdk/build/lib/librte_eal.a(eal.o): undefined reference
     to symbol 'pthread_create@@GLIBC_2.2.5'
     /lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from 
     command line

Nếu tôi cố gắng để xem các biểu tượng của libpthread, nó có vẻ tốt.

$ readelf -s /lib/x86_64-linux-gnu/libpthread.so.0 | grep pthread_create
   199: 0000000000008220  2814 FUNC    GLOBAL DEFAULT   13 pthread_create@@GLIBC_2.2.5
   173: 0000000000008220  2814 FUNC    LOCAL  DEFAULT   13 __pthread_create_2_1
   462: 0000000000008220  2814 FUNC    GLOBAL DEFAULT   13 pthread_create@@GLIBC_2.2

Bạn có thể đưa ra bất kỳ gợi ý hoặc con trỏ?



link_lologists (pthread)
Alex Punnen

# readelf -s /lib/x86_64-linux-gnu/libncurses.so readelf: Lỗi: Không thể định vị '/lib/x86_64-linux-gnu/libncurses.so'. Thông báo lỗi hệ thống: Quá nhiều cấp độ liên kết tượng trưng
Ashish Karpe

Bản sao DSO
luator

4
Khốn kiếp, tôi đã gcckhôngg++
Đăng tự

Câu trả lời:


162

Bạn nên đề cập đến thư viện trên dòng lệnh sau khi các tệp đối tượng được biên dịch:

 gcc -Wstrict-prototypes -Wall -Wno-sign-compare -Wpointer-arith -Wdeclaration-after-statement -Wformat-security -Wswitch-enum -Wunused-parameter -Wstrict-aliasing -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-field-initializers -Wno-override-init \
     -g -O2 -export-dynamic -o utilities/ovs-dpctl utilities/ovs-dpctl.o \
     lib/libopenvswitch.a \
     /home/jyyoo/src/dpdk/build/lib/librte_eal.a /home/jyyoo/src/dpdk/build/lib/libethdev.a /home/jyyoo/src/dpdk/build/lib/librte_cmdline.a /home/jyyoo/src/dpdk/build/lib/librte_hash.a /home/jyyoo/src/dpdk/build/lib/librte_lpm.a /home/jyyoo/src/dpdk/build/lib/librte_mbuf.a /home/jyyoo/src/dpdk/build/lib/librte_ring.a /home/jyyoo/src/dpdk/build/lib/librte_mempool.a /home/jyyoo/src/dpdk/build/lib/librte_malloc.a \
     -lrt -lm -lpthread 

Giải thích: việc liên kết phụ thuộc vào thứ tự các mô-đun. Các biểu tượng được yêu cầu đầu tiên, và sau đó được liên kết từ một thư viện có chúng. Vì vậy, bạn phải xác định các mô-đun sử dụng thư viện trước và thư viện sau chúng. Như thế này:

gcc x.o y.o z.o -la -lb -lc

Hơn nữa, trong trường hợp có sự phụ thuộc vòng tròn, bạn nên chỉ định cùng một thư viện trên dòng lệnh nhiều lần. Vì vậy, trong trường hợp libbcần ký hiệu từ libclibccần ký hiệu từ libb, dòng lệnh nên là:

gcc x.o y.o z.o -la -lb -lc -lb

23
Tôi nghĩ bạn có thể làm -Wl,--start-group -la -lb- -lc -Wl,--end-groupcho phụ thuộc tròn.
Z boson

2
Lưu ý điều này cũng áp dụng cho các tệp nguồn - chúng nên được liệt kê trước các thư viện. Bạn có thể nghĩ về các tệp đối tượng kết quả thay thế các tệp nguồn trong dòng lệnh và áp dụng thứ tự như trên.
jspencer

Nơi nào nên thêm -lpthread khi sử dụng make để xây dựng ứng dụng?
codezombie

50

Thông báo lỗi phụ thuộc vào phiên bản phân phối / trình biên dịch:

Ubuntu Saucy:

/usr/bin/ld: /mnt/root/ffmpeg-2.1.1//libavformat/libavformat.a(http.o): undefined reference to symbol 'inflateInit2_'
/lib/x86_64-linux-gnu/libz.so.1: error adding symbols: DSO missing from command line

Ubuntu Rared: (nhiều thông tin hơn)

/usr/bin/ld: note: 'uncompress' is defined in DSO /lib/x86_64-linux-gnu/libz.so.1 so try adding it to the linker command line

Giải pháp: Bạn có thể thiếu một thư viện trong các bước biên dịch của mình, trong giai đoạn liên kết. Trong trường hợp của tôi, tôi đã thêm '-lz' vào cờ makefile / GCC.

Bối cảnh: DSO là một đối tượng chia sẻ động hoặc thư viện dùng chung.


1
Tôi đã sử dụng giải pháp này để xây dựng một dự án khác cũng đưa ra lỗi tương tự bằng cách thêm -lz vào LDFLAGS và nó đã hoạt động hoàn hảo. Cảm ơn!
Mark Ellul

Lỗi vẫn còn đối với tôi: / usr / bin / ld: gaSim.o: tham chiếu không xác định đến ký hiệu 'pthread_create @@ GLIBC_2.1' /lib/i386-linux-gnu/libpthread.so.0: thêm các ký hiệu: DSO mất tích từ dòng lệnh
Aerox

Trong phần giải quyết thêm '-lpthread', nhưng bây giờ nó chỉ cho tôi: gaSim.c :( văn bản + 0x11d6):. Tài liệu tham khảo không xác định cho `glewInit'
Aerox

@Aerox: cho glewInit, bạn cần-lGLEW
mchiasson

19

Lý lịch

Các DSO missing from command linetin nhắn sẽ được hiển thị khi mối liên kết không tìm thấy biểu tượng cần thiết với nó là tìm kiếm thông thường nhưng biểu tượng có sẵn trong một trong những phụ thuộc của một thư viện động chỉ định trực tiếp.

Trong quá khứ, trình liên kết đã xem xét các biểu tượng trong các phụ thuộc của các ngôn ngữ được chỉ định là có sẵn. Nhưng điều đó đã thay đổi trong một số phiên bản sau và bây giờ trình liên kết thực thi một cái nhìn nghiêm ngặt hơn về những gì có sẵn. Do đó, thông điệp nhằm giúp chuyển đổi.

Phải làm sao?

Nếu bạn là người duy trì phần mềm

Bạn nên giải quyết vấn đề này bằng cách đảm bảo rằng tất cả các thư viện cần thiết để đáp ứng các ký hiệu cần thiết được chỉ định trực tiếp trên dòng lệnh của trình liên kết. Cũng nên nhớ rằng trật tự thường là vấn đề.

Nếu bạn chỉ đang cố gắng biên dịch phần mềm

Như một giải pháp thay thế, có thể chuyển trở lại chế độ xem dễ dãi hơn về những biểu tượng có sẵn bằng cách sử dụng tùy chọn -Wl,--copy-dt-needed-entries.

Các cách phổ biến để đưa phần này vào bản dựng là xuất LDFLAGS trước khi chạy configurehoặc tương tự như sau:

export LDFLAGS="-Wl,--copy-dt-needed-entries"

Đôi khi chuyển LDFLAGS="-Wl,--copy-dt-needed-entries"trực tiếp đến makecũng có thể làm việc.


gcc phiên bản 7.4.0 (Ubuntu 7.4.0-1ubfox1 ~ 18.04.1) không nhận ra cờ này.
UserX

1
Đây không phải là một tùy chọn gcc, vì vậy hoặc bạn đang thiếu -Wl,bit hoặc bạn có một trình liên kết không hỗ trợ tùy chọn này. Bạn đang sử dụng liên kết nào? Câu trả lời này giả định trình liên kết binutils cổ điển (ld.bfd). Các tài liệu liên kết vàng binutils (ld.gold) --copy-dt-needed-entrieslà "Không được hỗ trợ". Vì vậy, nếu bạn có (hoặc bất kỳ trình liên kết nào khác không hỗ trợ tùy chọn này) làm mặc định, bạn có thể cần phải theo dõi phần dành cho người bảo trì hoặc chuyển sang ld cổ điển để liên kết. Tôi nghĩ bạn có thể sử dụng -fuse-ld=ld.bfdcho điều đó.
texthell

14

Tôi tìm thấy một trường hợp khác và do đó tôi nghĩ rằng tất cả các bạn đều sai.

Đây là những gì tôi đã có:

/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: eggtrayicon.o: undefined reference to symbol 'XFlush'
/usr/lib64/libX11.so.6: error adding symbols: DSO missing from command line

Vấn đề là dòng lệnh DID KHÔNG chứa -lX11- mặc dù libX11.so nên được thêm vào như một phụ thuộc vì cũng có các thư viện GTK và Gnome trong các đối số.

Vì vậy, lời giải thích duy nhất cho tôi là tin nhắn này có thể nhằm giúp bạn , nhưng nó đã không thực hiện đúng. Điều này có lẽ đơn giản: thư viện cung cấp biểu tượng không được thêm vào dòng lệnh.

Xin lưu ý ba quy tắc quan trọng liên quan đến liên kết trong POSIX:

  • Các thư viện động đã xác định các phụ thuộc, vì vậy chỉ các thư viện từ phụ thuộc hàng đầu mới được cung cấp theo bất kỳ thứ tự nào (mặc dù sau các thư viện tĩnh)
  • Các thư viện tĩnh chỉ có các ký hiệu không xác định - tùy thuộc vào bạn để biết các phụ thuộc của chúng và cung cấp tất cả chúng trong dòng lệnh
  • Thứ tự trong các thư viện tĩnh luôn là: người yêu cầu trước , nhà cung cấp theo sau . Nếu không, bạn sẽ nhận được thông báo biểu tượng không xác định, giống như khi bạn quên thêm thư viện vào dòng lệnh
  • Khi bạn chỉ định thư viện với -l<name>, bạn sẽ không bao giờ biết liệu nó sẽ mất lib<name>.sohay lib<name>.a. Thư viện động được ưu tiên, nếu được tìm thấy và các thư viện tĩnh chỉ có thể được thực thi bằng tùy chọn trình biên dịch - đó là tất cả. Và cho dù bạn có bất kỳ vấn đề nào như trên hay không, điều đó phụ thuộc vào việc bạn có thư viện tĩnh hay động
  • Chà, đôi khi sự phụ thuộc có thể thiếu trong các thư viện động: D

Nó không chỉ nhằm mục đích giúp bạn, nó được yêu cầu bởi trình liên kết để giải quyết các tên trong câu hỏi. Lỗi hoàn toàn hợp lệ. Nếu trình biên dịch quyết định bỏ qua điều đó, bạn sẽ nhận được một segfault để truy cập vào thứ gì đó không có trong thời gian chạy nhị phân.
kevr

1
Để thêm, có thể là trên các nền tảng khác nhau, nguồn được biên dịch khác nhau; những gì được liên kết trên một hệ thống có thể không được liên kết trên một hệ thống khác. Điều này thường không phải là trường hợp, nhưng nó là hợp lý 100%.
kevr

Vấn đề không phải là nó không hợp lệ, mà là nó không thực sự hữu ích để tìm ra nguyên nhân của vấn đề.
Ethouris

7

Tôi thấy tôi có cùng một lỗi. Tôi đã biên dịch một mã với cả lapack và blas. Khi tôi chuyển thứ tự hai thư viện được gọi là lỗi đã biến mất.

"LAPACK_LIB = -llapack -lblas" hoạt động trong đó "LAPACK_LIB = -lblas -llapack" đã đưa ra lỗi được mô tả ở trên.


9
Tôi gặp lỗi này trong một dự án do cmake định nghĩa ... vậy có lỗi nào trong Cmake khiến thứ tự liên kết bị sai không?
peter karasev

trả lời @peterkaraev: thử sử dụng find_package(Threads)target_link_libraries( ... ${CMAKE_THREAD_LIBS_INIT})
activedecay

7

Tôi cũng gặp phải vấn đề tương tự. Tôi không biết tại sao, tôi chỉ cần thêm -lpthreadtùy chọn vào trình biên dịch và mọi thứ đều ổn.

Cũ:

$ g++ -rdynamic -m64 -fPIE -pie  -o /tmp/node/out/Release/mksnapshot ...*.o *.a -ldl -lrt

gặp lỗi sau. Nếu tôi thêm -lpthreadtùy chọn vào lệnh trên thì OK.

/usr/bin/ld: /tmp/node/out/Release/obj.host/v8_libbase/deps/v8/src/base/platform/condition-variable.o: undefined reference to symbol 'pthread_condattr_setclock@@GLIBC_2.3.3'
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

Điều này làm việc cho tôi; Tôi đã phải thêm một thứ hai, "dự phòng" -lpthread vào lệnh g ++ trong makefile có liên kết. (Nó đã xuất hiện một lần trong danh sách LIBS trong tệp tạo tệp.) Tôi cũng đã thêm "-L / lib / x86_64-linux-gnu" vào định nghĩa LDFLAGS trong tệp tạo tệp.
UserX

2

Những gì tôi đã tìm thấy là đôi khi thư viện mà trình liên kết phàn nàn không phải là nguyên nhân gây ra vấn đề. Có thể có một cách thông minh để tìm ra vấn đề ở đâu nhưng đây là điều tôi làm:

  • Nhận xét tất cả các thư viện được liên kết trong lệnh liên kết.
  • Dọn dẹp tất cả .Oo, .so, v.v. (Thường làm sạch là đủ, nhưng bạn có thể muốn chạy một tìm kiếm đệ quy + rm hoặc một cái gì đó tương tự).
  • Bỏ ghi chú các thư viện trong lệnh liên kết một lần và sắp xếp lại thứ tự khi cần thiết.

@peter karasev: Tôi đã gặp một vấn đề tương tự với dự án gcc 4.8.2 cmake trên CentOS7. Thứ tự của các thư viện trong phần "target_link_l library" rất quan trọng. Tôi đoán cmake chỉ chuyển danh sách cho trình liên kết, nghĩa là nó không thử và sắp xếp đúng thứ tự. Điều này là hợp lý - khi bạn nghĩ về nó, cmake không thể biết thứ tự đúng là gì cho đến khi liên kết được hoàn thành thành công.



1

Vấn đề tương tự xảy ra với tôi khi tôi sử dụng distccđể thực hiện dự án c ++ của mình; Cuối cùng tôi đã giải quyết nó với export CXX="distcc g++".


1

nếu bạn đang sử dụng cmake và pthreads đã sử dụng, hãy thử thêm các dòng sau

find_package(Threads)
target_link_libraries(${CMAKE_THREAD_LIBS_INIT})

0

Điều tương tự cũng xảy ra với tôi khi tôi cài đặt điểm chuẩn HPCC (bao gồm HPL và một vài điểm chuẩn khác). Tôi đã thêm -lmvào các cờ biên dịch trong tập lệnh xây dựng của mình và sau đó nó được biên dịch thành công.


3
Điều này không trả lời câu hỏi cụ thể này cũng như không đưa ra câu trả lời chung cho một gia đình có vấn đề tương tự. Đây là một câu trả lời địa phương hóa cao cho một câu hỏi khác hoàn toàn .
Hermann Döppes

0

Nếu sử dụng g++, hãy chắc chắn rằng bạn đang không chạy gccthay vì


3
Tại sao? Bạn có thể xây dựng một chút?
Ivan Ivković

0

Cố gắng thêm -pthreadvào cuối danh sách thư viện trong Makefile .

Nó làm việc cho tôi.


0

Nếu bạn đang sử dụng CMake, có một số cách bạn có thể giải quyết:

Giải pháp 1: Thanh lịch nhất

add_executable(...)
target_include_directories(...)
target_link_libraries(target_name pthread)

Giải pháp 2: sử dụng CMakefind_package

find_package(Threads REQUIRED) # this will generate the flag for CMAKE_THREAD_LIBS_INIT

add_executable(...)
target_include_directories(...)
target_link_libraries(target_name ${CMAKE_THREAD_LIBS_INIT})

Giải pháp 3: Thay đổi cờ CMake

# e.g. with C++ 17, change to other version if you need
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -pthread")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.