问题描述:
源文件中定义的函数是 : void setAccessKeyId(std::string)
但是使用centos中 g++4.8.5 编译能正常编译过,debian系统中使用 centos 10.2版本编译不过
提示找不到定义:setAccessKeyId(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
nm中查看库中定义的函数是这样的
setAccessKeyId(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
问题定位:
在使用Debian编译器时,不识别std::__cxx11::basic_string
的问题通常与编译器的ABI(应用程序二进制接口)和C++标准库的实现有关。具体分析如下:
- 编译器版本不一致:当项目中使用的第三方库与项目本身编译时所用的编译器版本不一致时,可能会导致
std::__cxx11::basic_string
未被识别的问题。 - C++标准库实现差异:在C++11标准中,
std::basic_string
的定义发生了变化,引入了新的名字空间std::__cxx11
以区分不同版本的实现。 - ABI兼容性问题:GCC 5及其以上版本引入了新的ABI,这可能导致使用旧版本ABI编译的代码与新版本ABI编译的代码之间的兼容性问题。
- 链接器错误:如果链接过程中出现了未定义的符号错误,可能是因为在链接时使用了不同的C++运行时实现,导致找不到对应的符号定义。
- 编译参数不一致:如果在编译项目文件时,使用的编译参数与第三方库编译时使用的参数不一致,可能会导致类型定义不匹配的问题。
- C库选择不同:不同的C++编译器可能默认使用不同的C++标准库实现,例如GCC默认使用libstdc++,而Clang默认使用libc++,这可能导致链接错误。
- 编译器默认行为改变:随着编译器版本的更新,其默认行为可能会发生改变,例如GCC 5开始默认启用C++11特性,这可能会影响到旧代码的兼容性。
- 源代码中的宏定义:如果在源代码中没有正确地定义
_GLIBCXX_USE_CXX11_ABI
宏,可能会导致编译器使用了不适当的ABI版本。
总之,为了解决这一问题,可以尝试以下几种方法:确保项目中所有的代码和第三方库都使用相同版本的编译器进行编译,以保持一致的ABI和符号定义。检查并调整编译参数,确保在编译项目时使用与第三方库相同的C++标准和标准库实现。如果是由于新版GCC引入的新ABI导致的兼容性问题,可以尝试在编译参数中添加-D_GLIBCXX_USE_CXX11_ABI=0
来使用旧版ABI。如果问题依旧存在,可以考虑更新项目中的代码,使其与C++11标准兼容,或者在必要时降级编译器版本以保持兼容性。
解决办法:
g++ 中添加 参数 : -D_GLIBCXX_USE_CXX11_ABI=0