C++ “运行时”;符号查找错误“;在编译和链接之后
首先,我已经搜索了这一个相当多,并没有设法找到一个问题与相同的情况 我正在64位机器上构建一个32位插件作为共享对象,并使用。cpp redis构建得很好,我使用cmake工具链强制使用32位,在构建过程中检查了.o文件并确认它们是32位的 我编译并链接了我的基本程序(包括一个主源文件和一个额外的库,用于与宿主应用程序对话,因为这是一个插件) 在运行将插件加载到主机应用程序时,我收到了以下信息:C++ “运行时”;符号查找错误“;在编译和链接之后,c++,g++,static-linking,C++,G++,Static Linking,首先,我已经搜索了这一个相当多,并没有设法找到一个问题与相同的情况 我正在64位机器上构建一个32位插件作为共享对象,并使用。cpp redis构建得很好,我使用cmake工具链强制使用32位,在构建过程中检查了.o文件并确认它们是32位的 我编译并链接了我的基本程序(包括一个主源文件和一个额外的库,用于与宿主应用程序对话,因为这是一个插件) 在运行将插件加载到主机应用程序时,我收到了以下信息: symbol lookup error: plugins/samp-redis.so: undefi
symbol lookup error: plugins/samp-redis.so: undefined symbol: _ZN9cpp_redis16redis_subscriberC1ERKSt10shared_ptrINS_7network10io_serviceEE
当我用-L将cpp redis dir添加到链接器路径,用-L将库添加到链接器路径时,我非常困惑,下面是我的comp/link行:
(SDK_DIR是我的主机应用程序SDK,非常小且最小的.c/h文件集)
它运行正常,没有错误,我使用-v运行了linkstage,以检查标志是否正确进入,看起来一切正常
(为可读性增加了一些新行)
我是误解了链接阶段还是静态链接?自从我做C++以来已经有一段时间了…这几天我对Python一窍不通
编辑: 使用
-W,--无未定义的
编译将导致此输出:
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure
-v
--with-pkgversion='Debian 4.9.2-10'
--with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs
--enable-languages=c,c++,java,go,d,fortran,objc,obj-c++
--prefix=/usr
--program-suffix=-4.9
--enable-shared
--enable-linker-build-id
--libexecdir=/usr/lib
--without-included-gettext
--enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.9
--libdir=/usr/lib
--enable-nls
--with-sysroot=/
--enable-clocale=gnu
--enable-libstdcxx-debug
--enable-libstdcxx-time=yes
--enable-gnu-unique-object
--disable-vtable-verify
--enable-plugin
--with-system-zlib
--disable-browser-plugin
--enable-java-awt=gtk
--enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre
--enable-java-home
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64
--with-arch-directory=amd64
--with-ecj-jar=/usr/share/java/eclipse-ecj.jar
--enable-objc-gc
--enable-multiarch
--with-arch-32=i586
--with-abi=m64
--with-multilib-list=m32,m64,mx32
--enable-multilib
--with-tune=generic
--enable-checking=release
--build=x86_64-linux-gnu
--host=x86_64-linux-gnu
--target=x86_64-linux-gnu
Thread model: posix
gcc version 4.9.2 (Debian 4.9.2-10)
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.9/
:/usr/lib/gcc/x86_64-linux-gnu/4.9/
:/usr/lib/gcc/x86_64-linux-gnu/
:/usr/lib/gcc/x86_64-linux-gnu/4.9/
:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.9/32/
:/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../lib32/
:/lib/../lib32/
:/usr/lib/../lib32/
:/usr/lib/gcc/x86_64-linux-gnu/4.9/
:/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../
:/lib/
:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-Wall' '-O2' '-m32' '-fshort-wchar' '-s' '-shared' '-L/usr/local/lib/' '-o' 'samp-redis.so' '-shared-libgcc' '-mtune=generic' '-march=i586'
/usr/lib/gcc/x86_64-linux-gnu/4.9/collect2
-plugin /usr/lib/gcc/x86_64-linux-gnu/4.9/liblto_plugin.so
-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
-plugin-opt=-fresolution=/tmp/ccOq8qY8.res
-plugin-opt=-pass-through=-lgcc_s
-plugin-opt=-pass-through=-lc
-plugin-opt=-pass-through=-lgcc_s
--sysroot=/
--build-id
--eh-frame-hdr
-m elf_i386
--hash-style=gnu
-shared
-o samp-redis.so
-s /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../lib32/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.9/32/crtbeginS.o
-L/usr/local/lib/
-L/usr/lib/gcc/x86_64-linux-gnu/4.9/32
-L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../lib32
-L/lib/../lib32
-L/usr/lib/../lib32
-L/usr/lib/gcc/x86_64-linux-gnu/4.9
-L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../..
-Bstatic
--no-undefined
-lcpp_redis amxplugin.o amxplugin2.o main.o
-lstdc++
-lm
-lgcc_s
-lc
-lgcc_s /usr/lib/gcc/x86_64-linux-gnu/4.9/32/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../lib32/crtn.o
/usr/bin/ld: cannot find
-lgcc_s
/usr/bin/ld: cannot find
-lgcc_s
collect2: error: ld returned 1 exit status
makefile:15: recipe for target 'build' failed
make: *** [build] Error 1
很明显,它找不到gcc_s,不管是什么?s=静态
我尝试搜索gcc库:
$ find /usr/ -name libgcc*
/usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc_eh.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/x32/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/4.9/x32/libgcc_eh.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/x32/libgcc.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/32/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/4.9/32/libgcc_eh.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/32/libgcc.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc_s_32.so
/usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc_s_x32.so
/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_eh.a
/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a
/usr/lib/x86_64-linux-gnu/libgccpp.so.1
/usr/lib/x86_64-linux-gnu/libgccpp.so.1.0.3
但是,执行ldconfig搜索时会显示名为libgcc.so.1的文件:
$ sudo /sbin/ldconfig -p | grep libgcc
libgccpp.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libgccpp.so.1
libgcc_s.so.1 (libc6,x32) => /usr/libx32/libgcc_s.so.1
libgcc_s.so.1 (libc6,x86-64) => /lib/x86_64-linux-gnu/libgcc_s.so.1
libgcc_s.so.1 (libc6) => /usr/lib32/libgcc_s.so.1
这可能是原因吗
谷歌搜索错误会带来一些结果,所以我会继续挖掘…即使您将cpp_redis构建为静态库,它也可以链接到共享库,它必须使用-fPIC标志编译,ie代码必须是可重定位的。在您的例子中,链接器在链接共享库时会自动忽略不兼容的代码。通过使用.so文件运行nm,您可以检查cpp_redis中的符号是否已解析到插件中
根据您的更新,您应该将您的插件链接到-W,--no未定义的而不是cpp\u redis。很可能它会失败,因为主机程序中的符号会丢失。但您可以检查cpp_redis中的符号是否被列为缺失。即使您将cpp_redis构建为静态库,它也必须使用-fPIC标志编译,即代码必须可重定位。在您的例子中,链接器在链接共享库时会自动忽略不兼容的代码。通过使用.so文件运行nm,您可以检查cpp_redis中的符号是否已解析到插件中
根据您的更新,您应该将您的插件链接到-W,--no未定义的而不是cpp\u redis。很可能它会失败,因为主机程序中的符号会丢失。但您可以检查cpp_redis中的符号是否被列为丢失。默认情况下,g++允许在构建共享库时包含未解析的符号,这些符号随后在运行时显示。尝试使用“-Wl,-no undefined”链接共享库,以明确强制定义所有符号。例如,您可能缺少要链接的其他库。顺便说一句。该符号似乎来自cpp_redis库,请确保在应用程序运行时,该库位于LD_library_路径(或Windows上的路径)中。可能是运行插件时无法找到并加载cpp_redis库。谢谢@axalis!关于g++允许未解析符号的部分是我想知道的,在文档中找不到。稍后我会尝试一下,因为我不明白为什么链接阶段运行得很好,但运行时没有。现在我有另一个问题(也许现在值得更多研究),但我觉得“静态链接”cpp redis将把所有内容都包含在我的.so文件中,因为我不希望插件用户需要构建/安装cpp redis项目,所以我宁愿将所有内容都放在一个包中。在你提到LD_LIBRARY_路径和“应用程序运行时”之前,我一直认为情况就是这样。如果方向正确,那就太好了!:)cpp_redis项目是否同时构建静态(*.a)和动态(*.so)库?如果是这样,并且它们位于同一位置,默认情况下将优先选择链接动态*.so的GCC。然后,您可以显式使用库名称(“libcpp_redis.a”而不是“-lcpp_redis”),将静态库重命名为例如libcpp_redic-static.a(并使用“-lcpp_redis-static”),或者优先使用静态库:“-Wl,-Bstatic-lcpp_redis”。默认情况下,g++允许在构建共享库时使用未解析的符号,然后在运行时显示。尝试使用“-Wl,-no undefined”链接共享库,以明确强制定义所有符号。例如,您可能缺少要链接的其他库。顺便说一句。该符号似乎来自cpp_redis库,请确保在应用程序运行时,该库位于LD_library_路径(或Windows上的路径)中。可能是运行插件时无法找到并加载cpp_redis库。谢谢@axalis!关于g++允许未解析符号的部分是我想知道的,在文档中找不到。稍后我会尝试一下,因为我不明白为什么链接阶段运行得很好,但运行时没有。现在我有另一个问题(也许现在值得更多研究),但我觉得“静态链接”cpp redis将把所有内容都包含在我的.so文件中,因为我不希望插件用户需要构建/安装cpp redis项目,所以我宁愿将所有内容都放在一个包中。在你提到LD_LIBRARY_路径和“应用程序运行时”之前,我一直认为情况就是这样。如果方向正确,那就太好了!:)cpp_redis项目是否同时构建静态(*.a)和动态(*.so)库?如果是这样,并且它们位于同一位置,默认情况下将优先选择链接动态*.so的GCC。然后,您可以显式地使用lib名称(“libcpp_redis.a”而不是“-lcp
$ find /usr/ -name libgcc*
/usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc_eh.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/x32/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/4.9/x32/libgcc_eh.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/x32/libgcc.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/32/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/4.9/32/libgcc_eh.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/32/libgcc.a
/usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc_s_32.so
/usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc_s_x32.so
/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_eh.a
/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a
/usr/lib/x86_64-linux-gnu/libgccpp.so.1
/usr/lib/x86_64-linux-gnu/libgccpp.so.1.0.3
$ sudo /sbin/ldconfig -p | grep libgcc
libgccpp.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libgccpp.so.1
libgcc_s.so.1 (libc6,x32) => /usr/libx32/libgcc_s.so.1
libgcc_s.so.1 (libc6,x86-64) => /lib/x86_64-linux-gnu/libgcc_s.so.1
libgcc_s.so.1 (libc6) => /usr/lib32/libgcc_s.so.1