Lỗi Linux c ++: tham chiếu không xác định đến 'dlopen'


147

Tôi làm việc trong Linux với C ++ (Eclipse) và muốn sử dụng thư viện. Eclipse cho tôi thấy một lỗi:

undefined reference to 'dlopen' 

Bạn có biết một giải pháp?

Đây là mã của tôi:

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char **argv) {
    void *handle;
    double (*desk)(char*);
    char *error;

    handle = dlopen ("/lib/CEDD_LIB.so.6", RTLD_LAZY);
    if (!handle) {
        fputs (dlerror(), stderr);
        exit(1);
    }

    desk= dlsym(handle, "Apply");

    if ((error = dlerror()) != NULL)  {
        fputs(error, stderr);
        exit(1);
    }

    dlclose(handle);
}

Câu trả lời:


254

Bạn phải liên kết với libdl, thêm

-ldl

để tùy chọn liên kết của bạn


2
Tôi đã gặp vấn đề tương tự ... Tôi đã thêm cờ trình biên dịch trong Project> Properties> C / C ++ Build> Settings> (My Linker)> Khác trong trường văn bản gắn cờ Liên kết. Nó không làm gì cả.
MirroredFate

3
Ha, ok, đối với bất kỳ ai khác có vấn đề này, hãy sử dụng đường dẫn trên, ngoại trừ đi tới Thư viện thay vì Linh tinh và thêm 'dl'
MirroredFate

2
Câu trả lời này đã giúp. Đối với bất kỳ ai muốn tìm vị trí của libdl.so, chỉ cần truy cập thư mục gốc và gõlocate libdl.so
Nav

Câu trả lời của MirroredFate cũng có tác dụng với tôi. Tôi không hiểu tại sao, mặc dù; mọi thư viện khác mà tôi từng phải liên kết hoạt động khi được đặt trong Linh tinh.
tổng

75

@Masci là chính xác, nhưng trong trường hợp bạn đang sử dụng C (và gcctrình biên dịch) sẽ tính đến việc này không hoạt động:

gcc -ldl dlopentest.c

Nhưng điều này không:

gcc dlopentest.c -ldl

Mất một chút để tìm ra ...


2
Tôi đã thấy rằng thứ tự của các tùy chọn cũng quan trọng. Trong một dự án sử dụng sqlite3, tôi phải đặt -ldl (và -lpthread) sau -lsqlite3. Không biết đó là gì, tôi chắc chắn câu trả lời là có nếu tôi chỉ RTFM.

Chúa ơi, thế thôi! Tôi sẽ không bao giờ đoán được rằng việc đặt các tùy chọn lên hàng đầu (điều này có ý nghĩa hơn với tôi) sẽ không hiệu quả, trong khi đặt chúng sau đó. Cảm ơn bạn, @knocte!
Joe Strout

@ user2918461 đánh vào đầu đinh. Tôi đã phải đặt -l theo thứ tự "chính xác".
NDEthos

vâng, rất vui khi có, nhưng không phải là ưu tiên để viết câu trả lời để giúp đỡ càng nhiều người càng tốt trong thời gian
knocte

8

Chủ đề này khá cũ, nhưng tôi đã đấu tranh với cùng một vấn đề ngày hôm nay trong khi biên dịch cegui 0.7.1 (điều kiện tiên quyết openVibe).

Điều làm việc cho tôi là thiết lập: LDFLAGS="-Wl,--no-as-needed" trong Makefile.

Tôi cũng đã cố gắng -ldlcho LDFLAGSnhưng không có kết quả.


8

cái này không hoạt động:

gcc -ldl dlopentest.c

Nhưng điều này không:

gcc dlopentest.c -ldl

Đó là một "tính năng" gây phiền nhiễu cho chắc chắn

Tôi đã vật lộn với nó khi viết cú pháp heredoc và tìm thấy một số sự thật thú vị . Với CC=Clang, điều này hoạt động:

$CC -ldl -x c -o app.exe - << EOF
#include <dlfcn.h>
#include <stdio.h>
int main(void)
{
  if(dlopen("libc.so.6", RTLD_LAZY | RTLD_GLOBAL))
    printf("libc.so.6 loading succeeded\n");
  else
    printf("libc.so.6 loading failed\n");
  return 0;
}
EOF

./app.exe

cũng như tất cả những điều này:

  • $CC -ldl -x c -o app.exe - << EOF
  • $CC -x c -ldl -o app.exe - << EOF
  • $CC -x c -o app.exe -ldl - << EOF
  • $CC -x c -o app.exe - -ldl << EOF

Tuy nhiên, với CC=gcc, chỉ có các biến thể cuối cùng hoạt động; -ldlsau -(ký hiệu đối số stdin).


5

bạn có thể thử thêm cái này

LIBS=-ldl CFLAGS=-fno-strict-aliasing

đến các tùy chọn cấu hình


1
Sử dụng biến LIBS làm việc cho tôi để có được cấu hình để đặt -ldl vào đúng vị trí trên dòng lệnh.
duncan

5

Tôi đã sử dụng CMake để biên dịch dự án của mình và tôi đã tìm thấy vấn đề tương tự.

Giải pháp được mô tả ở đây hoạt động giống như một bùa mê, chỉ cần thêm $ {CMAKE_DL_LIBS} vào lệnh gọi target_link_lologists ()


1
Cảm ơn! Điều này cũng giúp tôi. Nhưng chỉ sau khi tôi thay đổi trình biên dịch của mình thành tiếng kêu SET(CMAKE_CXX_COMPILER /usr/bin/clang++). Với / usr / bin / c ++ trên Ubuntu của tôi, nó không hoạt động ... (xem thêm câu trả lời của Vulcan raven)
thomasfermi

3

Bạn cần phải làm một cái gì đó như thế này cho makefile:

LDFLAGS='-ldl'
make install

Điều đó sẽ chuyển các cờ liên kết từ thực hiện đến liên kết. Không quan trọng rằng tệp tạo tệp đã được tự động tạo.



1

Để sử dụng các hàm dl, bạn cần sử dụng cờ -ldl cho trình liên kết.

Làm thế nào bạn làm điều đó trong nhật thực?

Nhấn Project -> Properties -> C / C ++ build -> Cài đặt -> GCC C ++ Linker ->
Thư viện -> trong hộp "Thư viện (-l)" nhấn dấu "+" -> ghi " Dl " (không có dấu ngoặc kép) -> nhấn ok -> dọn dẹp & xây dựng lại dự án của bạn.


1
 $gcc -o program program.c -l <library_to_resolve_program.c's_unresolved_symbols>

Một mô tả tốt về lý do tại sao vị trí của -l dl quan trọng

Nhưng cũng có một lời giải thích khá ngắn gọn trong các tài liệu từ $ man gcc

   -llibrary
   -l library
       Search the library named library when linking.  (The second
       alternative with the library as a separate argument is only for POSIX
       compliance and is not recommended.)
       It makes a difference where in the command you write this option; the
       linker searches and processes libraries and object files in the order
       they are specified.  Thus, foo.o -lz bar.o searches library z after
       file foo.o but before bar.o.  If bar.o refers to functions in z,
       those functions may not be loaded.
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.