gcc新旧版本ABI在项目中兼容性问题

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

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进行调用。

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值