不同 C/C++ 语言版本 + GNU 扩展的 ABI 兼容性

Posted

技术标签:

【中文标题】不同 C/C++ 语言版本 + GNU 扩展的 ABI 兼容性【英文标题】:ABI compatibility of different C/C++ language versions + GNU extensions 【发布时间】:2014-08-08 21:18:25 【问题描述】:

我目前正在使用没有 std 选项的 gcc 4.8.2 来编译我的 c/c++ 代码。 现在我想使用一些新的 C/C++ 语言版本的 c/c++ 提供的新特性。

(Un?)幸运的是 gcc 理解 C/C++ 的许多风格:

c90、c99、c11、gnu90、gnu99、gnu11 c++98、c++03、c++11、gnu++98、gnu++03、gnu++11

目前我在问自己:

是否需要为每个 c/c++ 版本提供一个单独的库,或者是否可以为多个 C/C++ 版本使用一个库? 特别是当我使用带有 gnu 扩展的相应 c/c++ 版本时,我可以链接使用特定 c/c++ 版本编译的库吗?

说明(基于 cmets)

请注意,我只使用一个编译器。不是只有修订号不同的两个 gcc。 当只使用一个 gcc 编译器时,我只要求不同标准选项之间的 ABI 不兼容。

【问题讨论】:

语言本身的风格不应该改变 ABI,只是编译器本身的不同版本。您可能不想将新编译器与使用 4.6 之前的编译器编译的库结合起来,但相当现代的 gcc 版本彼此兼容(至少在 x86 上)。 [大多数 C++ 标准模板库都是在头文件中实现的——因为它是“模板”,所以应该用编译器和头文件兼容的任何语言版本都可以正常编译] ABI 已经发生了很大变化。从 gcc 4.8.1 rev1 到 4.8.1 rev5,我必须重新编译整个静态库才能链接。否则它会给我未定义的符号等。从 4.7.2 到 4.8.1 更糟。如果它是动态库(.dll 或 .so),则链接在运行时完成并且工作正常。唯一担心的是 CRT 版本,很少会遇到崩溃/问题。对于静态库(.a 或 .lib 或 .o),这是一场噩梦。 @MatsPetersson - 对于 C ABI,这可能是一个合理的假设,但理论上 -std 选项可以调用不同的链接器选项。我不会依赖次要版本之间的 C++ 运行时库兼容性。 【参考方案1】:

一般:

你不能在同一个程序中组合不同的语言版本,这会导致许多库头文件中的“一个定义规则”违规。

在有限的情况下,您可能会发现一些类实际上不会随语言版本而改变。但是这种情况很少见,C++11 标准要求右值引用,而在 C++03 模式下根本不可用。

对于支持和不支持 GNU 扩展的版本,您可能会取得更大的成功,但您仍然需要通过预处理器运行每个标头,并验证编译器使用的是否看到完全相同的标记序列两种选择。

这与 ABI 更改完全不同,这可能会导致内存布局或名称修改在编译器变体之间有所不同。

您还可以通过避免使用任何特定于版本和语言的功能来避免在您自己的公共 API 上违反单一定义规则。本质上,这意味着一个扁平的 C API。

【讨论】:

以上是关于不同 C/C++ 语言版本 + GNU 扩展的 ABI 兼容性的主要内容,如果未能解决你的问题,请参考以下文章

树莓派Pico C/C++语言开发

树莓派Pico C/C++语言开发

树莓派Pico C/C++语言开发

如何为不同的 OS/Python 版本编译 Python C/C++ 扩展?

使用GNU/gdb调试Linux C/C++可执行程序查看出错源代码、设置断点

python学习(十七) 扩展python