'dlopen''ing 包含符号的 .so 会导致未定义的符号
`dlopen`'ing a .so that contains symbols results in undefined symbols
>问题
具体来说,我正在为我的应用程序使用cblas
。我创建了一个使用cblas
作为子例程的foo.so
,我dlopen('foo.so', RTLD_LAZY)
.
这是我用来编译的标志(编辑了一些-I
标志(:
g++-8 -std=c++17 -shared -O3 -xc++
-ffast-math -fPIC -fopenmp -lcblas - -o /mnt/xxx/python/test.so
这是我在dlopen()
时遇到的错误:
test.so: undefined symbol: cblas_dgemm
在这里我们看到cblas_dgemm
包含在.so
.
root@cd872c4b85ff:/mnt/xxx/python# objdump -TC test.so | grep cblas
0000000000000000 D *UND* 0000000000000000 cblas_ddot
0000000000000000 D *UND* 0000000000000000 cblas_dsyrk
0000000000000000 D *UND* 0000000000000000 cblas_dgemm
0000000000000000 D *UND* 0000000000000000 cblas_dgemv
但在ldd
中,它没有被列为依赖项。
root@cd872c4b85ff:/mnt/xxx/python# ldd test.so
linux-vdso.so.1 (0x00007ffdbb3c4000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f43f23a7000)
libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007f43f2177000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f43f1f5f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f43f1b6e000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f43f17d0000)
/lib64/ld-linux-x86-64.so.2 (0x0000562eb733a000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f43f15cc000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f43f13ab000)
我做了一个测试编译,它说-lcblas
已成功找到:
g++-8 -lcblas -Wl,--verbose | grep blas
attempt to open /usr/lib/gcc/x86_64-linux-gnu/8/libcblas.so failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/8/libcblas.a failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcblas.so succeeded
-lcblas (/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcblas.so)
/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
什么有效
一件重要的事情是,如果我将环境变量设置为LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libcblas.so
,可执行文件将正常运行。但是,这显然不是使可执行文件正常工作的正确方法。-Wl,rpath=
也不是正确的方式,因为 cblas 将驻留在不同的目录中(即在 OS X 上它在/usr/lib/libcblas.so
中,而在 ubuntu 中它是/usr/lib/x86_64-linux-gnu/libcblas.so
,我猜会有更多不可预测的位置(。
可能是什么原因?我没有正确链接它吗?动态链接器是否由于某种原因找不到符号?
由于某些信息已编辑,如果需要任何内容,请告诉我,我会将其添加到上面的信息中。谢谢。
编辑:符号确实存在于libcblas.so
:
root@3841c2760800:/usr/lib/x86_64-linux-gnu# nm -D libcblas.so | grep cblas_ddot
000000000000a0a0 T cblas_ddot
root@3841c2760800:/usr/lib/x86_64-linux-gnu# nm -D libcblas.so | grep cblas_dgemm
0000000000005790 T cblas_dgemm
root@3841c2760800:/usr/lib/x86_64-linux-gnu# nm -D libcblas.so | grep cblas_dgemv
00000000000077f0 T cblas_dgemv
root@3841c2760800:/usr/lib/x86_64-linux-gnu# nm -D libcblas.so | grep cblas_dsyrk
00000000000065f0 T cblas_dsyrk
编辑:
我相信,依赖关系图看起来像这样:
main --(dlopens)--> test.so
--(includes)--> header-only linear algebra library
--(calls cblas subroutine)--> /usr/lib/x86.../libcblas.so
所以 - 这是因为我的链接的顺序。我所做的是将C++文件(或字符串(流式传输到此 g++ 编译过程中。要流式传输,可以执行以下操作:
g++ ... -xc++ - ...
-xc++
告诉g++
它正在接收 c++ 文件(必需(,-
是文件字符串的占位符。在我的汇编中,我有:
g++ ... linker_flags ... -xc++ -
这意味着它实际上没有正确链接(linker_flags需要在文件名之后(。
我知道排序很重要,但是在这种情况下,当我流式传输文件时,我忘记了这个原则,这就是符号未定义的原因。
- vscode g++链路故障:体系结构x86_64的未定义符号
- 在 Mac 上使用 CMAKE 将 FFTW 和 FFTWPP 链接到项目中时未定义的符号
- 在C++中使用内联方法时出现未定义的符号错误
- 引擎节点:未定义的符号:_ZTV6Config
- 未定义的引用,尽管存在符号,但 std::experimental::可选
- 体系结构x86_64的未定义符号:std:terminate(),typeinfo,运算符delete[],运算符new
- Windows 链接器是否使用 LoadLibrary 解析 DLL 中未定义的符号?
- C++ 中 dlsym 的未定义符号
- MacOS 上的 Xcode 11 项目不在一个函数中使用 sin 和 cos:未定义的符号"___sincosf_stret"
- 仅在 MacOS 上析构函数的未定义符号
- OSX clang++:用于 cpp 文件中显式实例化模板的体系结构x86_64的未定义符号
- PCL 出错:体系结构x86_64 @pcl的未定义符号
- clang:错误:链接器命令失败,退出代码为 1(使用 -v 查看调用) - 体系结构的未定义符号 x86_64:
- 从 C++ 到 Python 的 SWIG:未定义的符号导入问题
- 使用静态变量未解析的外部符号/未定义的引用时出错
- 无法导出mexfunction:符号未定义的collect.exe2.exe:错误:ld返回1退出状态
- 模板生成错误:体系结构的符号未定义 x86_64:
- 继承-符号未定义
- __next_prime符号未定义
- 错误:对cv:: videoccapture::~ videoccapture()的引用符号未定义,命令行中缺少DSO