ข้อผิดพลาด Linux c ++: การอ้างอิงที่ไม่ได้กำหนดเป็น 'dlopen'


147

ฉันทำงานบน Linux ด้วย C ++ (Eclipse) และต้องการใช้ไลบรารี Eclipse แสดงข้อผิดพลาดให้ฉัน:

undefined reference to 'dlopen' 

คุณรู้วิธีแก้ปัญหาหรือไม่?

นี่คือรหัสของฉัน:

#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);
}

คำตอบ:


254

คุณต้องเชื่อมโยงกับ libdl เพิ่ม

-ldl

ตัวเลือก linker ของคุณ


2
ฉันพบปัญหาเดียวกัน ... ฉันเพิ่มคอมไพเลอร์แฟล็กภายใต้โครงการ> คุณสมบัติ> C / C ++ บิลด์> การตั้งค่า> (My Linker)> เบ็ดเตล็ดในฟิลด์ข้อความลิงเกอร์แฟล็กเลอร์ มันไม่ทำอะไรเลย
MirroredFate

3
ฮาโอเคสำหรับคนอื่นที่มีปัญหานี้ให้ใช้เส้นทางข้างต้นยกเว้นไปที่ห้องสมุดมากกว่าเบ็ดเตล็ดและเพิ่ม 'dl'
MirroredFate

2
คำตอบนี้ช่วยได้ สำหรับผู้ที่ต้องการค้นหาตำแหน่งของ libdl.so เพียงไปที่ไดเรกทอรีรากและพิมพ์locate libdl.so
Nav

คำตอบของ MirroredFate ก็ใช้ได้สำหรับฉันเช่นกัน ฉันไม่เข้าใจว่าทำไม ห้องสมุดอื่น ๆ ที่ฉันเคยมีเพื่อเชื่อมโยงทำงานเมื่ออยู่ในเบ็ดเตล็ด
รวม

75

@Masci ถูกต้อง แต่ในกรณีที่คุณใช้ C (และgccคอมไพเลอร์) ให้คำนึงว่ามันไม่ทำงาน:

gcc -ldl dlopentest.c

แต่สิ่งนี้จะ:

gcc dlopentest.c -ldl

เอาฉันไปคิดออก ...


2
ฉันพบว่าลำดับของตัวเลือกมีความสำคัญเช่นกัน ในโครงการที่ใช้ sqlite3 ฉันต้องใส่ -ldl (และ -lpthread) หลังจาก -lsqlite3 ไม่รู้ว่าเป็นอะไรฉันแน่ใจว่าคำตอบนั้นอยู่ที่นั่นถ้าฉันแค่ RTFM

อึศักดิ์สิทธิ์นั่นแหล่ะ! ฉันจะไม่เคยเดาเลยว่าการใส่ตัวเลือกก่อน (ซึ่งทำให้ฉันมีความหมายมากกว่า) ไม่ทำงานในขณะที่ทำให้พวกเขาทำหลังจากนั้น ขอบคุณ @knocte!
Joe Strout

@ user2918461 กระแทกเล็บที่หัว ฉันต้องใส่ -l ในลำดับ "ถูกต้อง"
ประสบการณ์ใกล้ตาย

ใช่มีความสุข แต่ไม่ใช่บุริมสิทธิ์สำหรับการเขียนคำตอบเพื่อช่วยคนให้มากที่สุดเท่าที่จะทำได้ในเวลาที่เหมาะสม
Knocte

8

หัวข้อนี้ค่อนข้างเก่า แต่ฉันต้องดิ้นรนกับปัญหาเดียวกันในวันนี้ในขณะที่รวบรวม cegui 0.7.1 (ข้อกำหนดเบื้องต้น openVibe)

สิ่งที่ใช้ได้ผลสำหรับฉันคือการตั้งค่า: LDFLAGS="-Wl,--no-as-needed" ใน Makefile

ฉันพยายาม-ldlด้วยLDFLAGSแต่ก็ไม่มีประโยชน์


8

สิ่งนี้ใช้ไม่ได้:

gcc -ldl dlopentest.c

แต่สิ่งนี้จะ:

gcc dlopentest.c -ldl

นั่นเป็นหนึ่งใน "คุณสมบัติ" ที่น่ารำคาญอย่างแน่นอน

ฉันกำลังต่อสู้กับมันเมื่อเขียนไวยากรณ์ heredoc และพบว่าบางส่วนข้อเท็จจริงที่น่าสนใจ ด้วยCC=Clangงานนี้:

$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

เช่นเดียวกับสิ่งเหล่านี้ทั้งหมด:

  • $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

อย่างไรก็ตามด้วยCC=gccการใช้งานตัวแปรสุดท้ายเท่านั้น -ldlหลัง-(สัญลักษณ์อาร์กิวเมนต์ stdin)


5

คุณสามารถลองเพิ่มสิ่งนี้ได้

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

ไปที่ตัวเลือกการกำหนดค่า


1
การใช้ตัวแปร LIBS นั้นทำให้ฉันได้รับการกำหนดค่าให้วาง -ldl ในตำแหน่งที่ถูกต้องบนบรรทัดคำสั่ง
duncan

5

ฉันใช้ CMake เพื่อรวบรวมโครงการของฉันและฉันพบปัญหาเดียวกัน

โซลูชันที่อธิบายไว้ที่นี่ใช้งานได้อย่างมีเสน่ห์เพียงแค่เพิ่ม $ {CMAKE_DL_LIBS} ในการโทร target_link_l ไลบรารี ()


1
ขอบคุณ! สิ่งนี้ช่วยฉันเช่นกัน SET(CMAKE_CXX_COMPILER /usr/bin/clang++)แต่หลังจากที่ผมเปลี่ยนคอมไพเลอร์ของฉันที่จะเสียงดังกราว ด้วย / usr / bin / c ++ บน Ubuntu ของฉันมันไม่ทำงาน ... (ดูคำตอบของ vulcan raven)
thomasfermi

3

คุณต้องทำสิ่งนี้สำหรับ makefile:

LDFLAGS='-ldl'
make install

นั่นจะส่งผ่านตัวเชื่อมโยงแฟล็กจากไม่ให้ผ่านไปยังตัวลิงก์ ไม่สำคัญว่า makefile จะถูกสร้างอัตโนมัติ



1

ในการใช้ฟังก์ชัน dl คุณต้องใช้แฟล็ก -ldl สำหรับตัวลิงก์

คุณทำอย่างไรใน eclipse

กดโครงการ -> คุณสมบัติ -> สร้างC / C ++ -> การตั้งค่า -> ตัวเชื่อมโยง GCC C ++ ->
ไลบรารี -> ในกล่อง "ไลบรารี (-l)" กดเครื่องหมาย"+" -> เขียน " dl " (โดยไม่ใส่เครื่องหมายอัญประกาศ) -> กดok -> ล้างและสร้างโครงการของคุณใหม่


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

คำอธิบายที่ดีว่าเหตุใดการวางตำแหน่งของ -l dl จึงสำคัญ

แต่ก็มีคำอธิบายสั้น ๆ เกี่ยวกับเอกสารจาก $ 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.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.