0

我环顾四周并尽力而为,但我无法解决这个问题:

我正在编译一个应用程序,它将动态加载用户创建的共享对象,例如 libmergestream.so。

mergestream.cpp(libmergestream.so 从中派生)包含 CImg 库调用。-lpthread -lX11 -lXext -lXrandr我用标志编译共享对象。

接下来,我将应用程序的第二部分构建为可执行文件,并提供相同的标志和库:-L/usr/lib/x86_64-linux-gnu通过链接器标志。

当我运行应用程序时,共享对象的加载失败并显示以下消息:

Sun Jun  3 19:35:24 2012[1,6]<stdout>:0x7f46705e4180 ../DALProcesses/lib/libmergestream.so: undefined symbol: XUnlockDisplay

为了确保没有遗漏任何内容,我采用了一个小型 CImg 库示例,并将其构建为可执行文件(无共享对象)。它运行良好。作为参考,我将其称为 CImgExample 二进制文件。

我在 CImgExample 二进制文件中查找符号:

nm CImgExample | grep 'XUn'
         U XUngrabKeyboard
         U XUnlockDisplay
         U XUnmapWindow

二进制文件本身有未定义的符号,我仍然可以让它执行。

对于 CImgExample 上的 ldd:

linux-vdso.so.1 =>  (0x00007fff988f5000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4f08e61000)
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f4f08b2d000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f4f0882c000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4f08532000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f4f0831c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4f07f5e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4f090ab000)
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f4f07d40000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4f07b3c000)
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f4f07938000)
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f4f07732000)

为了比较,这里是 libmergestream.so 的 nm 输出:

nm libmergestream.so | grep 'XUn'
                 U XUngrabKeyboard
                 U XUnlockDisplay
                 U XUnmapWindow

这是应用程序的 ldd(称为“main”),它将动态加载 libmergestream.so:

linux-vdso.so.1 =>  (0x00007fff8dfff000)
libmpi.so.1 => not found
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa79c69a000)
libmpi_cxx.so.1 => not found
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa79c495000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa79c195000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa79bf7e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa79bbc1000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa79c8e4000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa79b8c7000)

我注意到“main”中缺少这两个库引用:

libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f4f07938000)
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f4f07732000)

有趣的是,我在 Linux 服务器上为共享库和“主”运行相同的构建过程,一切顺利。是我的笔记本讨厌某些东西,我不知道是什么。

4

2 回答 2

2

此外,如果您的库中不需要 CImg 的显示功能,您可以禁用 X11,只需放置一个

#define cimg_display 0

就在“CImg.h”文件的包含之前。

于 2012-06-07T09:09:05.707 回答
1

你没有说,但看起来你在 Linux 上使用 gcc。如果是这样,请尝试使用 --no-undefined 标志构建 libmergestream.so 到 ld(如果您通过编译器驱动程序传递它,请使用 -Wl,--no-undefined)。这将使 libmergestream.so 的链接失败,除非在链接行上提供了满足其未定义符号所需的所有库。您可能会发现该链接现在因对这些相同符号的投诉而失败。您现在可以将任何所需的库添加到 libmergestream.so 的库列表中,直到链接成功。这些新的依赖项将被添加到库的“需要”集中,并在运行时与它一起加载。

这应该可以工作,除非 libmergestream.so 中有一些符号可以通过加载可执行文件本身来满足(在这种情况下应该使用 --export-dynamic 编译)。如果是这种情况,您可能无法使用 --no-undefined 一直到完整的链接,但您可以使用它来确定您仍需要添加哪些库:当唯一的符号链接失败是可执行文件提供的链接,您可以删除 --no-undefined ,此时您应该没问题。但是将支持抽象到另一个共享库中而不是依赖于可执行文件确实更好。对于您打算在运行时加载的库,如果可能的话,您应该使用 --no-undefined。

于 2012-06-05T15:54:33.633 回答