news 2026/4/23 4:06:20

设计心得——API和ABI以及ABI的兼容性

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
设计心得——API和ABI以及ABI的兼容性

一、工程实践需求

在开发的工程实践中,经常会遇到这些情况,在升级了动态库或相关的程序后,项目整体就无法启动了。甚至可能在运行时,直接就崩溃了。而在互联网的应用中,更愿意使用热补丁,即在不停止整体服务的情况下,替换相关的库(即不需要项目工程整体进行重新编译)。但很多情况下,这种需求的可能性是无法实现的,特别是在C++的应用中更是如此。一般来说,动态库HELL和上面的说明也有密切的关系。所以本文提到的问题主要是以动态库为主。
要想实现上述的问题,就需要提到C++的二进制兼容的问题,也就是今天重点分析的技术点。

二、ABI和API

API可能广为开发者熟悉,只要真正的做过开发的就一定接触过API,Application Programming Interface,应用程序编程接口。API是对外的(供开发者调用),API的种类划分方式有很多,包括按用途、系统、网络、硬件、范围等等。其核心的作用是:

  1. 分层和模块化处理
  2. 功能重用
  3. 安全和解耦
  4. 部署、测试等
    API并不是本文的重点,主要是引出ABI,Application Binary Interface,二进制应用接口。ABI是对内的(供机器调用的),主要用来处理多个二进制程序可以共同启动并运行。ABI在不同的平台上可能有不同的标准。比如在常见的X64平台上,就有Windows x64 ABI(MSVC C++ ABI)和 x86-64 System V ABI(Itanium C++ ABI )。不管是哪种ABI,其本质都是为协调在平台上的二进制的兼容性。它主要包括:
  5. 支持的处理器的指令集即各种CPU的支持机制
  6. 处理的基础类型、内存大小、内存布局以及对齐方式等各种数据表示机制
  7. 函数(包括虚函数机制)的调用机制、传参机制、栈的处理机制以及寄存器的应用方式(如返回值的寄存器处理、函数参数的寄存器应用方式等等)即函数调用约定机制
  8. 二进制文件的格式(这个非常重要,如ELF还是PE),即目标文件格式处理机制
  9. 操作系统或底层库(如Runtime Library)系统接口调用机制

开发者都知道要保证API的稳定性,但稳定的API并不一定能保证ABI的稳定和兼容性。API的升级可能导致ABI的不兼容从而导致程序运行的异常。API不兼容只会导致代码无法编译,而ABI不兼容则可能导致程序的无法运行。只有深刻的掌握了上述的机制,才能够从基础真正理解ABI的关键所在。而所谓的跨平台开发中,ABI兼容是一个非常被容易忽视的问题,往往在出现问题后才引起开发者的重视。

三、ABI兼容的控制

在了解了上述的相关ABI兼容的内容后

  1. 很可能影响ABI接口的开发方式
    a)类的继承和多态:增加或移除虚拟函数;增加或移除继承;修改继承体系内的类的成员顺序;重写多态函数
    b)类的各种限定、修饰符及数据类型等:如移除CV限定符或final、noexcept(当然如果确实无异常没有问题)等;修改返回值类型、参数类型、扩展或缩减参数以及权限控制等等
    c)类成员函数的控制:重载函数的增加及内联的控制(普通转内联 );对导出函数删除或更改函数签名等
    d)类成员变量控制:增加或删除非静态成员变量;改变其声明的顺序;对静态成员移除或取消导出,修改类型及更改CV限定符
    e)导出类的控制:取消或删除导出类
    f)模板类:任何修改模板参数的行为,如增、删、重排序等

  2. 不大可能影响ABI兼容性的开发方式
    a)类的继承:在严格控制下(如无多态),可对其按照下面的类成员进行修改
    b)枚举的控制:在现有的枚举内增加枚举定义
    c)类成员函数的控制:添加普通函数(含构造函数);删除非导出函数;修改函数参数默认值;增加函数的noexcept;修改函数名称;增减友元函数的声明
    d)类成员变量控制:修改成员变量名称;添加新的静态成员变量(不影响类的内存布局)
    e)导出类的控制:增加新的导出类
    f)宏控制:不会影响到接口本身导出的宏的修改和增加

四、ABI兼容问题实践

下面将针对影响ABI兼容控制相关的编程方法进行举例说明:

  1. 内存布局和内存对齐
    下面为导出的数据结构体定义:
//升级前structData{inti;charc;};//升级后structData{inti;charc;doubled;};//再升级后structData{charc;doubled;inti;};

增加了导出变量和修改了成员定义顺序后(占用空间不同)都可能导致ABI的稳定性。
2. 虚函数

//升级前structData{virtualvoidgetData(){}};structSubData:public Data{virtualvoidgetData(){}};//升级后structData{virtualvoidsetData(){}virtualvoidgetData(){}};structSubData:public Data{virtualvoidsetData(){}virtualvoidgetData(){}};

虚拟函数的修改会导致多态行为的接口改变影响ABI稳定性。
3. 参数和返回值的寄存器处理

//升级前structData{inta;intb;};class Demo{public:DatagetData(){}intsetValue(constData&d){}};//升级后structData{inta;intb;doubled;};class Demo{public:DatagetData(){}intsetValue(constData&d){}};

这种情况增加了成员影响了返回值的处理。特别是在传参处理上,有些平台允许将16字节大小的结构体拆成两个8字节的部分使用寄存器传参。
4. 编译器处理
编译器选项的选择对ABI的影响也不小,比如优化级别:-O1,-O2等等;RTTI控制-fno-rtti;字节对齐-fpack-struct[=n] 等等。不同的平台可能相关编译选项也有不同,可参看相关的文档工具查看
5. 其它
还有不少的细节可以控制和影响ABI兼容性,如调用约定、其中有一个解决机制非常不错,在前面也分析过,0长度数组:

structData{inta;intb;charbuf[0];};

这种方式就可以既兼容ABI的稳定又可以在一定程度上扩展相关的数据。不过,它不是在所有平台通用的,需要注意。

五、常用的ABI兼容方法

虽然实现C/C++的ABI兼容难度很大,但在工程实践中也总结了几个不错的办法。主要有:

  1. 使用位域
    直接操作位对于任何的平台来说,基本都是一样的,所以它可以最大可能的保持ABI兼容
  2. 使用Pimpl机制,尽最大可能的隔离隐藏。这样,就把ABI的兼容性隔离到了一个很小的范围内
  3. 使用隔离隐藏机制,如上面提到的零长度数组和类分布式的方法如消息、事件等,隐藏ABI兼容的细节
    除了上述的开发上的技术应用外,还可以在技术管理上进行控制:
  4. 应用静态库。这个就不用解释了,全包含了,哪里还有什么升级、替换的问题。不过,静态库也有其缺点,要慎重
  5. 严格控制动态库的版本管理 ,防止DLL HELL的问题

六、总结

其实ABI兼容问题,对于C/C++这种中低级语言来说是一个大问题。但对于更现代的高级语言,ABI兼容已经被隔离在了开发之外,像C#和Java等,它们很多都运行在各自的虚拟环境上,很多ABI兼容的细节问题自然已经被屏蔽掉。有些问题会随着技术的演进而自然被解决掉。这也是那句名言,要用发展的眼光看问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 7:41:30

开题报告_基于Python的网络爬虫的设计与实现

目录研究背景与意义研究目标技术路线创新点预期成果参考文献项目技术支持可定制开发之功能亮点源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作研究背景与意义 随着互联网数据爆炸式增长,网络爬虫成为高效获取结构化信息的关键技…

作者头像 李华
网站建设 2026/4/19 2:50:27

WordPress如何实现WORD文档图片的无损保存至博客?

要求:开源,免费,技术支持 博客:WordPress 开发语言:PHP 数据库:MySQL 功能:导入Word,导入Excel,导入PPT(PowerPoint),导入PDF,复制粘贴word,导入微信公众号内容,web截屏 平台:Window…

作者头像 李华
网站建设 2026/4/18 8:10:35

Word表格题注自动设置全攻略

基础设置:自动为表格添加题注打开Word选项中的高级设置,找到插入题注相关配置。 通过引用选项卡中的插入题注功能,选择自动插入题注选项。 勾选Microsoft Word表格,设置标签为"表"并确定位置为所选项目上方。自定义题注…

作者头像 李华
网站建设 2026/4/16 11:05:43

MongoDB 分布式存储与查询优化:从副本集到分片集群

MongoDB 作为高性能文档型 NoSQL 数据库,凭借灵活的 schema、高并发读写、分布式扩展能力,成为大数据量、高并发场景的核心存储方案。但默认配置下,MongoDB 存在索引缺失导致查询缓慢、分片键选择不当引发数据倾斜、事务一致性难保障、副本集…

作者头像 李华
网站建设 2026/4/18 6:19:02

摆脱论文困扰!千笔,深得人心的AI论文工具

你是否曾为论文选题发愁,反复修改却仍不满意?面对复杂的格式要求和查重压力,是不是感到力不从心?对于MBA学生而言,论文不仅是学术能力的体现,更是毕业的关键一环。而如今,有了千笔AI&#xff0c…

作者头像 李华