【C++调试】"undefined symbol: xxx" 相关问题的查找、定位与解决方法


背景

开发多个动态库链接在一起的程序,编译生成动态链接库后,调用时出现 "undefined symbol" 问题:

#011加载动态库 /backupsoft/AnyBackupServer/EOSSService/components/libeossdataservice.so 失败,错误原因:/backupsoft/AnyBackupServer/EOSSService/components/libeossdataservice.so: undefined symbol: _ZN6ncMaskD1Ev

 

定位与解决方法

(1)使用 nm 命令:确认是否真的有未定义的函数,导致在函数符号表中找不到

1 [root@model components]# nm -u libeossdataservice.so | grep _ZN6ncMaskD1Ev 
2 U _ZN6ncMaskD1Ev 

 

(2)使用file 命令查看 so库的架构,看看是否与平台一致

可以看到,当前so库架构为x86-64,可以在GNU/Linux平台下使用。平台与架构一致

[root@model components]# file libeossdataservice.so
libeossdataservice.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=c43127eb5590ae5238f9f04a7dc530a8acfe586d, not stripped

 

 

 

 接下来,需要定位一下 undefined symbol的具体信息

(3)通过 ldd -r xxx.so 命令查看so库链接状态和错误信息

ldd命令,可以查看对应的可执行文件或库文件依赖哪些库,但可执行文件或库文件要求与操作系统的编译器类型相同,即电脑是X86的GCC编译器,那么无法通过ldd命令查看ARM交叉编译器编译出来的可执行文件或库文件。

如果想在Ubuntu等Linux宿主机上查看ARM交叉编译好的可执行程序和库文件的相关依赖关系,可以通过以下命令:
readelf -d xxx.so | grep NEEDED

[root@model components]# ldd -r libeossdataservice.so
linux-vdso.so.1 => (0x00007ffce43fa000)
libimmtrans.so => /backupsoft/AnyBackupServer/EOSSService/libimmtrans.so (0x00007f20123fe000)
libmask.so => /backupsoft/AnyBackupServer/EOSSService/libmask.so (0x00007f20121fc000)
libesafec.so => /backupsoft/AnyBackupServer/EOSSService/libesafec.so (0x00007f2011fe9000)
libbasecore.so => /backupsoft/AnyBackupServer/EOSSService/libbasecore.so (0x00007f2011c05000)
libappcore.so => /backupsoft/AnyBackupServer/EOSSService/libappcore.so (0x00007f20118ed000)
libkeymgm.so => /backupsoft/AnyBackupServer/EOSSService/libkeymgm.so (0x00007f20116cb000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f20113c4000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f20111ae000)
libc.so.6 => /lib64/libc.so.6 (0x00007f2010de0000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f2010bc4000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f20109c0000)
librt.so.1 => /lib64/librt.so.1 (0x00007f20107b8000)
librecrypto.so => /backupsoft/AnyBackupServer/EOSSService/librecrypto.so (0x00007f20103a9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2012a19000)
libressl.so => /backupsoft/AnyBackupServer/EOSSService/libressl.so (0x00007f2010148000)
libm.so.6 => /lib64/libm.so.6 (0x00007f200fe46000)
undefined symbol: _ZN6ncMaskD1Ev (./libeossdataservice.so)        // 扩展名D1Ev是C++ 析构函数
undefined symbol: _ZN6ncMaskC1Ev (./libeossdataservice.so)        // 扩展名C1Ev是C++ 构造函数
[root@model components]#

可以看到有两个 undefined symbol ,其中就有提到的 _ZN6ncMaskD1Ev 和 _ZN6ncMaskC1Ev 错误

(4)使用 c++filt <symbol> 定位错误在那个C++文件中:c++filt 可查看函数被 name mangling (名字修饰) 前的函数名字符

1 [root@model components]# c++filt _ZN6ncMaskD1Ev
2 ncMask::~ncMask()
3 
4 [root@model components]# c++filt _ZN6ncMaskD1Ev
5 ncMask::~ncMask()

 

原因总结

1.检查Makefile/CMakeList.txt,查看是否包含所有需要包含的文件/文件夹。 错误原因:有时候由于新添加了一个文件/文件夹,而该文件/文件夹又没有被Makefile/CMakeList.txt扫描到,这时候就会在实际运行时出现undefined symbol,原因是编译时找到了对应的头文件,却在链接时未找到需要的头文件。

2.查看对应函数在头文件和Cpp文件中是否有相同的函数结构。 错误原因:有时候往往是先把一堆头文件先写好,结果在写实现时容易忘记写一两个函数实现,然后就容易编译过了,但链接时没过,因为链接时需要把头文件和Cpp文件链接在一起。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM