• Linux 编译链接那些事儿(02)C++链接库std::__cxx11::basic_string和std::__1::basic_string链接问题总结


    1 问题背景说明

    在自己的项目源码中引用libeasysqlite.so时编译成功,但运行时遇到问题直接报错,找不到符号 symbol:_ZN3sql5FieldC1ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_10field_typeEi。

    2 问题描述和解读

    使用c++filt查看符号表中未知的这个符号

    1. $c++filt _ZN3sql5FieldC1ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_10field_typeEi
    2. sql::Field::Field(std::__1::basic_string, std::__1::allocator >, sql::field_type, int)

    查询到该符号对应的真实函数为:

    sql::Field::Field(std::__1::basic_string, std::__1::allocator >, sql::field_type, int)

    接下来在使用nm命令查询libeasysqlite.so,看是否有该符号对应的函数。使用nm命令查看,如下所示:

    1. .../data/sqlite/build$ nm -gC libeasysqlite.so |grep sql::Field::Field
    2. 000000000002fca0 T sql::Field::Field(sql::field_use)
    3. 000000000002fd80 T sql::Field::Field(std::__cxx11::basic_string, std::allocator >, sql::field_type, int)
    4. 0000000000038394 W sql::Field::Field(sql::Field&&)
    5. 00000000000320c4 W sql::Field::Field(sql::Field const&)
    6. 000000000002fca0 T sql::Field::Field(sql::field_use)
    7. 000000000002fd80 T sql::Field::Field(std::__cxx11::basic_string, std::allocator >, sql::field_type, int)
    8. 0000000000038394 W sql::Field::Field(sql::Field&&)
    9. 00000000000320c4 W sql::Field::Field(sql::Field const&)

    这里发现并没有我们需要的sql::Field::Field(std::__1::basic_string, std::__1::allocator >, sql::field_type, int)方法,而是有一个类似的sql::Field::Field(std::__cxx11::basic_string, std::allocator >, sql::field_type, int)方法,这就说明有可能是编译时使用的链接库不同而导致的问题。

    这里是cxx11空间,对应的是 C++11版本的链接库,而我们需要的是__1空间的库,也就是C++03版本的链接库。那么如何修改呢?就是在CMakeList.txt文件中添加一些参数,如下所示:

    1. set(CMAKE_CXX_COMPILER clang++-14)
    2. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")

    重新编译libeasysqlite.so库。这样在编译生成库的时候就会强制使用C++03版本的标准了,再次make编译出sql库即可。

    接下来开始测试该库。修改后执行nm命令查看,如下所示:

    1. .../data/sqlite/build$ nm -gC libeasysqlite.so |grep sql::Field::Field
    2. 00000000000244b0 T sql::Field::Field(sql::field_use)
    3. 0000000000024590 T sql::Field::Field(std::__1::basic_string, std::__1::allocator >, sql::field_type, int)
    4. 00000000000244b0 T sql::Field::Field(sql::field_use)
    5. 0000000000024590 T sql::Field::Field(std::__1::basic_string, std::__1::allocator >, sql::field_type, int)
    6. 0000000000029e54 W sql::Field::Field(sql::Field&&)
    7. 000000000002734c W sql::Field::Field(sql::Field const&)

    这样就和我们需要的对上了。

    3 问题总结

    该类问题的解决步骤如下所示:

    1. 遇到这类问题时基本上都是使用c++filt来将符号表中的符号转换。
    2. 确认符号是否在库中,如果不在库中那么可能是链接库的版本或者编译方式不对。
    3. 修正编译方式/库的版本,确认符号表中的符号可以对上。接下来进行实测即可。

  • 相关阅读:
    基于分时电价策略的家庭能量系统优化附Matlab代码
    怎么把jfif格式改成jpg?
    Sality 病毒的驱动模块分析报告
    2023高教社杯数学建模国赛B题思路解析+代码+论文
    财产清查概述、 全面清查的情况、局部清查的情况、财产清查的方法、财产清查结果的处理
    稻米之缘农耕稻作文化 国稻种芯-万祥军:影响中国历史走向?
    【AI视野·今日Robot 机器人论文速览 第五十二期】Wed, 11 Oct 2023
    Apollo planning之PathAssessmentDecider
    如何绑定 Webhook 推送
    网络隔离后 不同部门如何实现不同的跨网传输审批?
  • 原文地址:https://blog.csdn.net/vviccc/article/details/134208200