
undefined symbol: _ZdlPvm, version Qt_5错误以及error while loading shared libraries: xxx.so解析
ldd 命令,用于查找某个动态库所依赖的库是否存在# 找不到的库会出现 not found...nm 命令,用于读取库被导出的符号readelf 用于读取 elf 文件的相关信息c++filt 用于获取符号的原始名。
今天在ubuntu系统编译一个qt项目的时候,遇到了如下报错:
/home/aruchid/Qt5.12.1/5.12.1/gcc_64/bin/uic: symbol lookup error: /home/aruchid/Qt5.12.1/5.12.1/gcc_64/bin/uic: undefined symbol: _ZdlPvm, version Qt_5
make[2]: *** [cloudtool/CMakeFiles/cloudtool_autogen.dir/build.make:71:cloudtool/CMakeFiles/cloudtool_autogen] 错误 1
make[1]: *** [CMakeFiles/Makefile2:271:cloudtool/CMakeFiles/cloudtool_autogen.dir/all] 错误 2
make: *** [Makefile:136:all] 错误 2
经过初步的分析,发现可能有几个原因
-
符号查找错误:这表明
uic
工具尝试访问一个它找不到的符号(_ZdlPvm
),这通常是因为库文件不匹配或者缺失某些必要的库。_ZdlPvm
是C++的删除操作符delete
的mangled(混淆后的)名称,涉及特定版本的Qt库。 -
版本问题:错误中提到了
version Qt_5
,这可能表明你的环境中安装的Qt库版本和uic工具期望的版本不匹配。这可以由多个版本的Qt库存在或环境变量设置不正确导致。依赖库未找到
后面经过分析,我确定是Qt安装的版本和系统使用的QT版本不一致,程序运行默认先从系统的 /usr/lib/x86_64-linux-gnu/目录查找动态库,编译的使用了Qt5.12.1,而系统目录是其他的版本,所以会出现未定义的错误;不能替换系统目录下的Qt库,否则系统会崩溃。
可能的解决办法:
- 使用 ldd -r , 确定系统库中是否存在所依赖的库
- 执行 ldconfig 命令更新 ld 缓存
- 执行 ldconfig -p | grep {SO_NAME} 查看是否能找到对应的库
- 检查 LD_LIBRATY_PATH 是否设置了有效的路径
在CMake中指定程序运行时引用特定的动态库(如Qt库)通常涉及到几个方面的设置,包括编译时的链接和运行时的环境配置。在CMakeLists.txt文件中,你可以控制编译时链接到的Qt库,但运行时库的路径主要是通过环境变量或操作系统的配置来管理的。
为了简化开发和测试,可以通过设置LD_LIBRARY_PATH
(Linux/Mac)或PATH
(Windows)环境变量来指示操作系统在运行时查找库的位置。这可以在用户的shell配置文件中设置,或在应用程序的启动脚本中设置:
export LD_LIBRARY_PATH="/path/to/Qt5.12.1/5.12.1/gcc_64/lib:$LD_LIBRARY_PATH"
通过上述方法,你可以确保你的应用程序在编译时和运行时都使用指定版本的Qt库。这对于避免版本冲突和运行时错误非常重要,特别是在依赖特定库功能或避免系统库冲突时。
其实简单来说就是,通过设置环境变量来指定程序运行查找的库。
然后又遇到了如下的问题: ./cloudtool: error while loading shared libraries: libQt5X11Extras.so.5: cannot open shared object file: No such file or directory
这个错误表明你的应用程序在尝试运行时未能找到libQt5X11Extras.so.5
这个共享库文件。这通常是因为库文件不在系统期望的库路径中,或者相关的环境变量没有正确设置。以下是解决这个问题的步骤:
首先,确保你的系统中安装了Qt5X11Extras
模块,并找到libQt5X11Extras.so.5
文件的位置。通常这个库文件位于Qt安装目录下的lib
文件夹内。你可以使用find
命令来帮助查找:
find /home/aruchid/Qt5.12.1/5.12.1/gcc_64/ -name libQt5X11Extras.so.5
找到库文件后,你需要确保这个库文件的路径被添加到LD_LIBRARY_PATH
环境变量中。这样操作系统在运行时就可以找到它:
export LD_LIBRARY_PATH=/path/to/Qt5.12.1/5.12.1/gcc_64/lib:$LD_LIBRARY_PATH
确保替换路径为实际的路径,其中包含libQt5X11Extras.so.5
。
或者也可以使设置永久生效
如果你不想每次打开新终端时都重新输入这条命令,可以将其添加到你的用户配置文件中,例如~/.bashrc
或~/.bash_profile
(取决于你的shell和操作系统):
echo 'export LD_LIBRARY_PATH=/home/aruchid/Qt5.12.1/5.12.1/gcc_64/lib:$LD_LIBRARY_PATH' >> ~/.bashrc source ~/.bashrc
这将确保每次你打开一个新的终端窗口时,LD_LIBRARY_PATH
都已正确设置。
另一个解决方案是设置可执行文件的RPATH,这样它会在特定的目录下搜索库,而无需设置环境变量。这可以通过修改CMakeLists.txt来实现,如下所示:
set(CMAKE_INSTALL_RPATH "/home/aruchid/Qt5.12.1/5.12.1/gcc_64/lib") set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
命令总结
ldd 命令,用于查找某个动态库所依赖的库是否存在,它是 Linux 系统中用于查看可执行文件或动态链接库(共享库)依赖的动态链接库(库文件)的工具。它显示了一个程序在运行时将会加载哪些库,以及这些库的位置。
ldd example
linux-vdso.so.1 (0x00007ffce8dab000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1e8b1d1000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1e8b5c1000)
这里,每行都表示一个库依赖:
- 第一列显示库的名称。
- 第二列使用箭头
=>
显示库文件的路径(如果找到的话)。 - 第三列显示库文件加载到内存中的地址(可选信息,视系统而定)。
注意事项
- 如果某个库没有找到,
ldd
通常会在相应的行显示not found
。 - 使用
ldd
命令时需要谨慎,因为这个命令实际上会加载指定的库,如果库中有恶意代码,可能会造成安全风险。对不信任的二进制文件使用ldd
时应特别小心。
nm 命令,用于读取库被导出的符号
$ nm -gDC libSXVideoEngineJni.so | grep -i license
0000000000008110 T __ZN13SXVideoEngine6Public7License10SetLicenseEPKc
0000000000008130 T __ZN13SXVideoEngine6Public7License13LicenseStatusEv
0000000000008190 T __ZN13SXVideoEngine6Public7License19IsVideoCutSupportedEv
0000000000008170 T __ZN13SXVideoEngine6Public7License26IsDynamicTemplateSupportedEv
0000000000008150 T __ZN13SXVideoEngine6Public7License26IsStadardTemplateSupportedEv
readelf 用于读取 elf 文件的相关信息
$ readelf -d libSXVideoEngineJni.so | grep rpath
0x000000000000000f (RPATH) Library rpath:
[/home/slayer/workspace/SXVideoEngine-Core/Render/cmake-build-
debug:/home/slayer/workspace/SXVideoEngine-Core/Render/../../SXVideoEngine-Core-Lib/blend2d/linux/lib]
c++filt 用于获取符号的原始名
$ c++filt __ZN13SXVideoEngine6Public7License10SetLicenseEPKc
SXVideoEngine::Public::License::SetLicense(char const*)
更多推荐
所有评论(0)