C++ 尝试使用dlopen加载库时未定义的符号

C++ 尝试使用dlopen加载库时未定义的符号,c++,compilation,linker,shared-libraries,dlopen,C++,Compilation,Linker,Shared Libraries,Dlopen,我正在尝试加载一个共享库(插件),我是在LinuxARM平台下用dlopen提供的(封闭源代码)。我尝试以这种方式加载: void* handle = dlopen(<library_path>/<library_name>, RTLD_NOW); void*handle=dlopen(/,RTLD_NOW); 结果是此消息失败: Failed to load <library_path>/<library_name>: undefined s

我正在尝试加载一个共享库(插件),我是在LinuxARM平台下用dlopen提供的(封闭源代码)。我尝试以这种方式加载:

void* handle = dlopen(<library_path>/<library_name>, RTLD_NOW);
void*handle=dlopen(/,RTLD_NOW);
结果是此消息失败:

Failed to load <library_path>/<library_name>: undefined symbol: <symbol_name>.
加载失败/:未定义的符号:。
我试图用nm查看库内部,但似乎库已被剥离,找不到任何符号。我还尝试使用readelf-s,事实上,我得到了以下结果:

12663: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND <symbol_name>
12663:00000000不键入全局默认值
通过阅读,我得到readelf-s返回所有符号,包括它引用的库中定义的符号

这个问题的答案对我来说并不完全清楚:这是一个应该在图书馆里的符号,它不在图书馆里,因为它是以错误的方式编译的,还是一个我应该在其他地方找到的符号?readelf-d的输出似乎表明我提供了所有需要的共享库。这个错误可能与我编译可执行文件时的错误有关,还是与加载程序无关


此外,我还了解了每列的含义,但这些值非常奇怪。您如何解释该符号描述?为什么地址是0?为什么类型为NOTYPE?

未定义的符号:X表示始终应该从加载的库之一导出X,但它不是。您应该找出所请求的符号在哪个库中,并链接到它

您应该知道,此消息总是由库的问题引起的,而不是错误。图书馆应该知道如何获取所有的符号。若并没有,你们可以将你们的可执行文件链接到所需的库,这样当你们加载插件时,所需的符号就已经被知道了


这个错误可能有更复杂的原因。若插件和主应用程序都链接到库,那个么尝试链接可能会以未定义的符号结束。如果主应用程序和插件使用不同版本的库(即插件使用较新版本),则可能会发生这种情况。然后在加载插件时,旧版本已经加载,所以加载程序假设一切正常,但新版本可能包含新符号。如果插件使用它们,您将得到未定义的符号错误。

如果链接命令中静态库的顺序对于应用程序来说是错误的,那么这个问题也会出现。Unix ld链接器要求在引用函数的库之后指定实现函数的库

当我试图从自定义位置(不是来自主机的标准libz,而是从源代码手动构建)获取libz库来构建libteseract共享库时,遇到了这个问题。我举了一个例子:

错误的链接顺序(-lz之前-llept):

用“nm-D”检查:

使用“dlopen”进行检查:

之所以会发生这种情况,是因为链接器在循环中处理在命令行中传递的所有静态库,跳过了前面的库未使用的库。由于在检查libz.a时,链接器看到所有已检查的库都没有使用libz.a中的任何函数,因此链接器只是“忘记”了libz.a

正确的链接顺序(-lz在-Llett之后):

用“nm-D”检查:


“dlopen”这次没有显示此错误。

使用
nm-D
,而不仅仅是
nm
。您现在是否特别应该使用
RTLD\u
?否则,您可能只需要切换到
RTLD\u LAZY
@n.m.:Arg!我真的不知道。“符号列为:U”。@DavidSchwartz:嗯,我不确定,但我认为更好的办法是理解为什么会发生这种情况,并注意到这一点。重点还是学习。
文件
返回什么?如果我对/lib/libm-2.11.1.0运行它,那么我会得到“ELF 32位LSB…,stripped”并运行
nm/lib/libm-2.11.1。所以
我会得到“无符号”。但是按照@n.m.的说法,我得到了一个函数列表。它们必须是可见的,否则任何程序将如何工作。我无法加载库,因为版本不匹配..谢谢+1
$ g++  -fPIC -DPIC -shared -nostdlib /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/5/crtbeginS.o  -Wl,--whole-archive ....(some libs) -Wl,--no-whole-archive  -L/home/build/jenkins/workspace/tesseract/zlib/bin/lib -L/home/build/jenkins/workspace/tesseract/leptonica/bin/lib -L/usr/lib/gcc/x86_64-linux-gnu/5 -L/usr/lib/x86_64-linux-gnu -lz -llept -lstdc++ -lm -lc -lgcc_s /usr/lib/gcc/x86_64-linux-gnu/5/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o  -g -O2   -Wl,-soname -Wl,libtesseract.so.4 -o .libs/libtesseract.so.4.0.1
$ nm -D .libs/libtesseract.so.4.0.1 | grep deflateInit
                 U deflateInit_
Cannot load ./tesseract/src/api/.libs/libtesseract.so.4.0.1 (./tesseract/src/api/.libs/libtesseract.so.4.0.1: undefined symbol: deflateInit_)
$ g++  -fPIC -DPIC -shared -nostdlib /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/5/crtbeginS.o  -Wl,--whole-archive ....(some libs) -Wl,--no-whole-archive  -L/home/build/jenkins/workspace/tesseract/zlib/bin/lib -L/home/build/jenkins/workspace/tesseract/leptonica/bin/lib -L/usr/lib/gcc/x86_64-linux-gnu/5 -L/usr/lib/x86_64-linux-gnu  -llept -lz -lstdc++ -lm -lc -lgcc_s /usr/lib/gcc/x86_64-linux-gnu/5/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o  -g -O2   -Wl,-soname -Wl,libtesseract.so.4 -o .libs/libtesseract.so.4.0.1
$ nm -D .libs/libtesseract.so.4.0.1 | grep deflateInit
000000000041fb5b T deflateInit_
000000000041fba3 T deflateInit2_