alldying 2025-11-26 14:06 采纳率: 0%
浏览 9

linux dlopen undefined symbol

动态库a继承了动态库b的一个类CXXX,主程序dlopen动态库a的时候报undefined symbol: _ZTI13CXXX,动态库静态调用了动态库c、d、e,编译动态库b时-frtti -Wl,-export-dynamic,-rdynamic都试过了,请问是什么原因呢?

  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2025-11-26 14:22
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    你遇到的 undefined symbol: _ZTI13CXXX 是一个典型的 C++ RTTI(Run-Time Type Information) 相关的问题。这个问题通常发生在使用 dlopen 动态加载动态库时,未正确导出或链接 RTTI 信息


    🚨 问题分析

    1. 符号 _ZTI13CXXX 的含义

    • 这是一个 C++ 编译器生成的 RTTI 类型信息符号
    • 它表示类 CXXX 的类型信息(_ZTI 表示 type_info)。
    • 当主程序通过 dlopen 加载动态库 A 时,如果该动态库中定义了继承自动态库 B 中的类 CXXX,而主程序或其它依赖库没有正确导出这个 RTTI 符号,就会报错。

    ✅ 可能的原因

    1. 动态库 A 没有导出 RTTI 符号

      • 即使你使用了 -Wl,-export-dynamic-Wl,-rdynamic某些情况下仍然无法导出 RTTI 符号
      • 特别是当类 CXXX 是从另一个动态库 B 继承而来时,RTTI 符号可能没有被正确导出。
    2. 动态库 B 没有正确编译或链接

      • 如果动态库 B 没有使用 -frtti,那么其类的 RTTI 信息不会被生成。
      • 或者 B 在构建时没有正确导出符号,导致 A 中的类 CXXX 的 RTTI 信息缺失。
    3. 主程序没有使用 -Wl,--export-dynamic

      • 即使动态库 A 正确导出了 RTTI 符号,主程序在调用 dlopen 时也需要确保这些符号可以被解析。
      • 使用 --export-dynamic 可以让主程序导出所有符号,包括 RTTI。
    4. 动态库之间存在依赖关系问题

      • 动态库 A 依赖于 B,B 又依赖于 C、D、E 等其他库,但这些依赖关系没有被正确处理,可能导致 RTTI 信息丢失。

    🔧 解决方案

    1. 确保所有相关动态库都启用了 -frtti

    # 编译动态库 B
    g++ -fPIC -shared -frtti -o libb.so b.cpp
    
    # 编译动态库 A
    g++ -fPIC -shared -frtti -o liba.so a.cpp -L. -lb
    

    注意: 所有涉及 CXXX 类的动态库(如 B、A)都需要启用 -frtti


    2. 使用 -Wl,--export-dynamic 编译主程序和动态库

    # 编译主程序(使用 --export-dynamic)
    g++ -o main main.cpp -Wl,--export-dynamic
    
    # 编译动态库 A(使用 --export-dynamic)
    g++ -fPIC -shared -frtti -Wl,--export-dynamic -o liba.so a.cpp -L. -lb
    

    重点: 主程序必须使用 --export-dynamic,否则即使动态库导出了符号,也无法被解析。


    3. 检查动态库之间的依赖关系

    使用 ldd 查看动态库的依赖关系:

    ldd liba.so
    

    确保 liba.so 正确链接了 libb.so 和其他依赖库(如 C、D、E)。


    4. 使用 nmobjdump 检查符号是否导出

    nm -D liba.so | grep _ZTI13CXXX
    
    • 如果输出为空,说明该符号没有被导出。
    • 如果有输出,说明符号已经导出,可能是主程序没有正确加载。

    5. 尝试显式导出符号(使用 .def 文件)

    你可以创建一个 .def 文件来显式导出符号:

    LIBRARY liba.so
    EXPORTS
    _ZTI13CXXX
    

    然后在编译时指定:

    g++ -fPIC -shared -frtti -Wl,--export-dynamic -Wl,--output-def=liba.def -o liba.so a.cpp -L. -lb
    

    注意: 不同平台的 .def 文件格式可能不同,建议优先使用 --export-dynamic 方法。


    ✅ 总结

    | 问题原因 | 解决方案 | |----------|-----------| | 动态库未启用 -frtti | 所有相关动态库添加 -frtti | | 主程序未使用 --export-dynamic | 主程序添加 -Wl,--export-dynamic | | RTTI 符号未正确导出 | 使用 nm 检查符号,或使用 .def 显式导出 | | 动态库依赖关系错误 | 使用 ldd 检查依赖关系 |


    💡 额外建议

    • 如果你使用的是 CMake,可以在 target_link_libraries 中添加:

      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti")
      set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--export-dynamic")
      
    • 如果你使用的是 GCC/Clang,可以尝试使用 -fvisibility=hidden + __attribute__((visibility("default"))) 来控制符号导出。


    如果你提供具体的编译命令或代码片段,我可以进一步帮你定位问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 11月26日