17

我知道原则上这可能是未定义的行为,但为了处理大型项目,这是我关于 GCC 的问题:

假设我使用完全相同的编译器安装编译一个转换单元gcc -std=c++98和另一个转换单元。-std=c++11是否有任何保证可以链接两个目标文件并获得定义明确的程序?

据我所知,由于宏的不同,潜在的问题只能来自库头的不同视图,而这些反过来最多只会向标准库类添加新的成员函数,但绝不会添加成员对象。

这会以某种方式使编译具有不同语言方言选项的大型项目的不同部分变得可以接受吗?

更新:我应该添加一个正交问题:如何使用两个不同版本的 GCC(比如 4.3 和 4.6),但是使用相同的方言选项(-std=c++98)?此 GCC 文档中的列表似乎表明该库在 4.2.2 和 4.6 之间的两个方向上都兼容。

4

3 回答 3

9

先验的,没有。最安全的解决方案是假设所有编译器选项都是相同的,除非编译器专门记录该选项不会影响二进制兼容性。(大多数编译器都非常缺乏文档。)在实践中,在缺乏文档的情况下,控制警告的选项(-W...在 g++ 中)不会影响二进制兼容性,而影响代码生成的选项(语言级别等)可能:g++ 通常在不同级别的优化之间保持兼容性,而 VC++ 则没有。

另一个真正的问题是在命令行中定义预处理器符号。同样,最安全的赌注是所有定义都是相同的,但同样,一些常识是有序的:很难期望标准库已经使用项目中使用的预处理器符号进行编译(例如MYPROG_CONFIG_FILE_LOCATION, )。另一方面,请注意预处理器定义_GLIBCXX_DEBUGand_GLIBCXX_DEBUG_PEDANTIC会影响二进制兼容性(尽管 g++ 确保如果您始终使用它们,您将获得与它们一起使用的库版本)。

关于您的问题:由于标准版本,我不希望对二进制兼容性产生太大影响,但是如果选择会影响某些预定义的预处理器符号,我不会感到惊讶,这会破坏库中的二进制兼容性,就好像你编译了一些带有 的模块_GLIBCXX_DEBUG,而有些没有。它可能会起作用,但我不会指望它。

于 2012-05-23T09:53:53.470 回答
3

我知道原则上这可能是未定义的行为,

它不是。

假设我使用完全相同的编译器安装编译一个转换单元gcc -std=c++98和另一个转换单元。-std=c++11是否有任何保证可以链接两个目标文件并获得定义明确的程序?

是的,这是受支持且有效的(有例外,例如在一个对象中启用调试模式而不是另一个,或者使用显式 ABI 更改选项,例如在一个对象中而不是另一个对象-fshort-enums中,但这应该很明显,因为那不会即使您-std对两个对象使用相同的选项也可以工作)。

据我所知,由于宏的不同,潜在的问题只能来自库头的不同视图,而这些宏又最多会向标准库类添加新的成员函数,但绝不会添加成员对象。

正确的。

这会以某种方式使编译具有不同语言方言选项的大型项目的不同部分变得可以接受吗?

对于 GCC,是的,绝对是。作为证明它是可以的,考虑它libstdc++.so本身包含一些用 构建的对象-std=c++98和一些用-std=c++14.

更新:我应该添加一个正交问题:如何使用两个不同版本的 GCC(比如 4.3 和 4.6),但是使用相同的方言选项(-std=c++98)?此 GCC 文档中的列表似乎表明该库在 4.2.2 和 4.6 之间的两个方向上都兼容。

不是双向,您需要使用libstdc++.so来自 GCC 4.6(或更高版本)的,因为使用该版本编译的对象可能依赖于新版本中引入的符号并且不存在于旧libstdc++.so库中。

https://stackoverflow.com/a/49119902/981959上的一些相关信息

于 2018-03-05T22:15:00.317 回答
0

语言 ABI 相同,但 STL ABI 不同。见https://gcc.gnu.org/wiki/Cxx11AbiCompatibility

所以不建议混合使用 -std=c++98 -std=c++11 编译的库。跨图像边界传递数据时可能会发生崩溃。

(如果您只调用 extern "C" 函数并且只传递 POD,它可能会起作用)。

另见相关:Mixing different C++ standards with GCC

于 2018-03-05T22:55:18.300 回答