链接C 17,C 14和C 11对象是否安全

假设我有三个编译对象,都是由相同的编译器/版本生成的:

> A是用C 11标准编写的
> B是用C 14标准编制的
> C是用C 17标准编译的

为简单起见,我们假设所有头文件都是用C 11编写的,只使用其语义在所有三个标准版本之间没有变化的构造,因此任何相互依赖性都通过头包含正确表达,编译器没有反对.

这些对象的组合是什么,链接到单个二进制文件是不安全的?为什么?

编辑:欢迎涵盖主要编译器(例如gcc,clang,vs)的答案

解决方法:

Which combinations of these objects is it and isn’t it safe to link into a single binary? Why?

对于GCC,将对象A,B和C的任意组合链接在一起是安全的.如果它们都使用相同的版本构建,那么它们是ABI兼容的,标准版本(即-std选项)没有任何区别.

为什么?因为这是我们实施的重要属性,我们努力确保.

如果您遇到问题,如果您将使用不同版本的GCC编译的对象链接在一起,并且在GCC对该标准的支持完成之前,您已使用新C标准中的不稳定功能.例如,如果使用GCC 4.9和-std = c 11编译对象,而使用GCC 5和-std = c 11编译另一个对象,则会出现问题. C 11支持在GCC 4.x中是实验性的,因此GCC 4.9和5版本的C 11特征之间存在不兼容的变化.类似地,如果使用GCC 7和-std = c 17编译一个对象,而使用GCC 8和-std = c 17编译另一个对象,则会遇到问题,因为GCC 7和8中的C 17支持仍然是实验性的和不断发展的.

另一方面,以下对象的任何组合都将起作用(尽管请参阅下面有关libstdc .so版本的说明):

>使用GCC 4.9和-std = c 03编译的对象D.
>使用GCC 5编译的对象E和-std = c 11
>使用GCC 7编译的对象F和-std = c 17

这是因为C 03支持在所有使用的三个编译器版本中都是稳定的,因此C 03组件在所有对象之间是兼容的. C 11支持自GCC 5以来是稳定的,但是对象D不使用任何C 11特征,对象E和F都使用C 11支持稳定的版本. C 17支持在任何使用的编译器版本中都不稳定,但只有对象F使用C 17特性,因此与其他两个对象没有兼容性问题(它们共享的唯一功能来自C 03或C 11,以及使用的版本使这些部分OK).如果您以后想要使用GCC 8和-std = c 17编译第四个对象,那么您需要使用相同的版本重新编译F(或者不链接到F),因为F和G中的C 17符号不兼容.

上述D,E和F之间兼容性的唯一警告是您的程序必须使用GCC 7(或更高版本)中的libstdc .so共享库.因为对象F是使用GCC 7编译的,所以您需要使用该版本的共享库,因为使用GCC 7编译程序的任何部分可能会引入对来自GCC 4.9或GCC 5的libstdc .so中不存在的符号的依赖性.类似地,如果链接到使用GCC 8构建的对象G,则需要使用GCC 8中的libstdc .so来确保找到G所需的所有符号.简单的规则是确保程序在运行时使用的共享库至少与用于编译任何对象的版本一样新.

在你的问题的评论中已经提到的使用GCC的另一个警告是,自从GCC 5以来,libstdc中有两个std :: string实现.这两个实现不是链接兼容的(它们具有不同的错位名称,因此不能链接在一起)但可以共存于同一个二进制文件中(它们具有不同的错位名称,因此如果一个对象使用std,请不要冲突: :string和另一个使用std :: __ cxx11 :: string).如果您的对象使用std :: string,那么通常它们都应该使用相同的字符串实现进行编译.编译-D_GLIBCXX_USE_CXX11_ABI = 0选择原始的gcc4兼容实现,或-D_GLIBCXX_USE_CXX11_ABI = 1选择新的cxx11实现(不要被名称欺骗,它也可以在C 03中使用,它被称为cxx11,因为它符合C 11要求).默认情况下,哪种实现取决于GCC的配置方式,但在编译时始终可以使用宏覆盖默认值.

上一篇:c – 在bool中设置额外位会使其同时为true和false


下一篇:go-ipfs-abi初步使用