ABI
这里与我们常用的API的概念一起拿出来对比认识。
API全称:Application Program Interface
An API defines the interfaces by which one piece of software communicates with another at the source level.
ABI全称:Application Binary Interface
Whereas an API defines a source interface, an ABI defines the low-level binary interface between two or more pieces of software on a particular architecture. It defines how an application interacts with itself, how an application interacts with the kernel, and how an application interacts with libraries.
可以参考这个链接difference-between-api-and-abi
兼容性问题
由于在gcc5.1版本中,libstdc++库中使用了新版本的底层string和list,为了与原有方式兼容,引入了新版本的ABI。即是gcc5.1之后,默认含有string类型的函数,其函数签名不一样。
例如:void Get(std::string str);
旧版本ABI的函数签名为:
_Z3GetSs
使用c++filt转换为:Get(std::basic_string<char, std::char_traits, std::allocator >)
新版本ABI函数签名为:
_Z3GetNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
使用c++filt转换为:Get(std::__cxx11::basic_string<char, std::char_traits, std::allocator >)
可以分析使用c++filt工具进行转换查看函数原型。
可以看到,新版本的ABI,在string前加了__cxx11作为类型前缀。
另外,如果函数参数中,不含有std::string类型或者std::list类型,则正常情况下不存在ABI兼容性问题
例如:void Set(int a);
不管是新版本ABI还是旧版本ABI,其函数签名均为:
_Z3Seti
注:新旧版本的ABI,可以在GCC5.1之后版本编绎的时候,如果使用C++11标准,定义_GLIBCXX_USE_CXX11_ABI 这个宏为0表示使用旧版本ABI,1新版本(默认)
升级GCC版本可能带来的问题
如果升级的GCC版本在5.1以下,还是使用老版本的ABI,正常情况下,不会有ABI兼容性问题。
如果升级的GCC版本在5.1以上,使用c++11标准编绎的时候,默认使用了新版本的ABI。则可能对于项目中依赖的第三方的库,存在使用上的兼容性问题。如果是动态链接,则在启动的时候,会提示找不到对应的函数实现,即是典型的undefined symbol问题。
原因分析:
假设:A项目使用了B库(假设是动态库),B库在生成的过程中,使用的是旧版本的GCC进行编绎,自然ABI就是老版本。如果A库使用了5.1以上的GCC,且使用C++11标准的默认编绎,且使用的B库接口中含有string类型的参数。则A库在运行过程中,会提交对应的函数定义,即是undefined symbol。
原因是A的代码中需要寻找找的是新版本的ABI,而B库中生成的是老版本的ABI,两者虽然函数原型定义一样,但在库交互的层面,会找不到。
解决方案
1、最简单暴力的做法,就是把A库项目全部使用老版本的ABI来编绎。
成本:就是A上依赖的很多库,必须全部使用旧版本的ABI来安装。(例如依赖了新版本的protobuf,安装的时候使用了C++11的5.1以后的版本,则需要修改其源码安装配置,重新使用旧版本ABI来安装,否则会出现undefined symbol问题)
2、尝试去找B库的源码,看是否能使用新版本的ABI来编绎解决。
3、如果找不到B库的源码,尝试找B库的新版本库,看是否有支持新版本ABI。
4、写一个中间代理层,C库。C库中包含B库的静态链接,C库暴露出来的函数接口,不含有string和list。C库编绎的时候,使用旧版本ABI去链接B库即可。A库在使用C库的时候,由于接口中并不含有string和list,则可以使用新ABI进行调用。

GCC 5.1版本后引入了新的ABI,导致libstdc++中的string和list函数签名改变,可能引发兼容性问题。当升级GCC到5.1及以上并使用C++11标准时,可能会遇到第三方库的ABI不匹配,表现为undefined symbol错误。解决方案包括使用旧版本ABI编译项目、修改第三方库源码、寻找支持新ABI的新版本库或创建中间代理库。
1万+

被折叠的 条评论
为什么被折叠?



