C++ “运行时”;符号查找错误“;在编译和链接之后

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

首先,我已经搜索了这一个相当多,并没有设法找到一个问题与相同的情况

我正在64位机器上构建一个32位插件作为共享对象,并使用。cpp redis构建得很好,我使用cmake工具链强制使用32位,在构建过程中检查了.o文件并确认它们是32位的

我编译并链接了我的基本程序(包括一个主源文件和一个额外的库,用于与宿主应用程序对话,因为这是一个插件)

在运行将插件加载到主机应用程序时,我收到了以下信息:

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