• 【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文件链接在一起。

  • 相关阅读:
    【JAVA、C++】LeetCode 005 Longest Palindromic Substring
    【JAVA、C++】LeetCode 004 Median of Two Sorted Arrays
    【JAVA、C++】LeetCode 003 Longest Substring Without Repeating Characters
    【JAVA、C++】LeetCode 002 Add Two Numbers
    【JAVA、C++】LeetCode 001 Two Sum
    Linux的文件管理
    Ubuntu及Windows ADB设备no permissions的解决方案
    4-[多进程]-互斥锁、Queue队列、生产者消费者
    3 [多进程]-开启多进程
    2-[多进程]-进程理论
  • 原文地址:https://www.cnblogs.com/SchrodingerDoggy/p/15464919.html
Copyright © 2020-2023  润新知