多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

拯救 C 语言 ABI:透明别名能否解决兼容性难题?

拯救 C 语言 ABI:透明别名能否解决兼容性难题? 1. 拯救 C 语言为何先拯救 ABI2022 年 3 月 13 日作者上一篇关于应用二进制接口ABI稳定性的文章发表后此次文章标题令人意外它与 Jason Turner 在 C Weekly 上“打破 ABI 以拯救 C”的主题相悖。Jason 的观点正确作者上一篇文章也展示了实现者反向修改标准库及以 ABI 威胁新特性的情况。但作者却声称要拯救 ABI这引发疑问难道 ABI 不该被摧毁作者是否被收买或疯了实际上作者头脑清醒未被收买。作者意识到即便鼓吹更好的标准库、编写高性能代码系统也不会因部分人而改变但这并不意味着要放弃因为打破 ABI 的方法不止一种。2. 可怕的 ABI 是什么应用二进制接口ABI是编译器对计算机硬件资源逐位表示和使用方式的假设。在 C 或 C 代码中创建结构体或编写函数时就相当于签署了无形契约。其涵盖 struct/class 成员位置等多方面。本文主要关注 C 语言其 ABI 重要的是 struct 成员位置和函数参数、返回类型。由于 C 纳入 C 标准库C 语言的 ABI 问题也成了 C 的问题且 C 语言决策影响所有人。3. C 语言的 ABI 如何体现C 语言的 ABI 是函数与二进制文件中生成的符号基本一一对应。例如声明 do_stuff 函数不同参数类型生成的汇编代码不同。将参数从 long long 改为 __int128_t 后汇编代码有明显变化这表明编译器与编写函数定义的人达成了“契约”这就是 ABI。C 有“名称修饰”可避免符号混淆而 C 语言几乎没有实现采用。C 语言编译代码的 call 指令只包含函数名这导致其符号不稳定。4. 从另一个角度看 ABI 会怎样实现 do_stuff 函数long long 类型和 __int128_t 类型版本的代码和汇编差异大。若应用程序错误链接到不同版本可能会出问题。5. 故意制造问题会如何通过两个 .c 文件一个声明 long long 类型的 do_stuff 函数一个定义 __int128_t 类型的 do_stuff 函数编译时链接器不在意类型不匹配但运行时可能出现访问冲突等未定义行为。即便函数放在头文件中问题仍可能出现。6. 意外引发的 ABI 问题有哪些ABI 问题可能在编译器前端和链接器不报错时出现库是新的问题来源。C 语言不进行名称修饰共享库时需大家就符号达成一致。在 *nix 系统中动态库更新需保持向后兼容性。小示例在调试模式有错误弹窗但关键系统组件发布版本可能出现段错误问题根源和症状难关联。使用错误头文件编译编译器默认同名东西按预期运行会导致很多问题还会延迟特性采用通常延迟 10 到 11 年如 C99 引入特性到 C11 变为可选特性、Python 2.x 到 Python 3 的过渡、C11 中 std::string 写时复制机制的改变。7. 这还算好的结果吗C 情况如此C 语言标准委员会若无法解决兼容性问题可能更糟。如 realloc 函数处理大小为 0 的内存块问题DR 400 未完全解决最终 N2464 被纳入 C23 标准。这表明标准由实现者决定实现者不满则改变无法通过。8. 但……为什么是 ABI这和 Victor Zverovich 的 fmtlib 在 C20 到 C23 期间情况类似以不改变行为为由不遵循标准是强大武器。标准委员会通常不做成本高或实现者不想做的改变陷入两难局面很多讨论都会遇到类似情况。不过某些平台有解决办法。9. 一个古老的解决方案是什么为系统发行版设计的健壮 C 库使用汇编标签技术NetBSD 已用超过 25 年。该技术可在不改变顶层代码时重命名最终二进制文件中的符号很多 C 实现有不同方式实现目标都是将 NormalName 替换为 _BinarySymbolNamemusl libc 就用此技术实现兼容性。那么为何不用于解决 ABI 问题呢10. 透明别名能解决问题吗论文 [N2901] 讨论了提供最终二进制文件中正式符号的方法目标是使用成本为零、不使用无额外成本、不引入新函数或符号。该功能规范类似“函数的 typedef”多个平台有相关实践能在 Clang 中实现。示例代码显示无论是否优化生成的汇编代码都未提及别名。透明别名能在不被 ABI 锁定旧行为束缚的情况下让新代码使用相同名称访问新行为和语义。用户可根据宏定义选择不同接口和实现新编译代码可升级而不影响旧使用者。但因没有共享认可的解决方案拒绝实现的实现者可拒绝改进影响生态系统。intmax_t 相关问题受 ABI 影响难解决。那么这个解决方案能解决问题吗在 [Godbolt.org] 上有实现该功能的编译器设置完整测试使用修改构建 Clang 编译器能解决主流平台的 ABI 问题吗11. ABI 测试maxabs文章未完整阐述此部分内容。
返回列表