可以将不同的GCC方言联系在一起吗?

问题描述 投票:18回答:3

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

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

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

这会以某种方式使用不同的语言方言选项编译更大项目的不同部分是否可以接受?

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

c++ gcc linker undefined-behavior dialect
3个回答
10
投票

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

另一个真正的问题是在命令行中定义预处理程序符号。同样,最安全的选择是所有定义都是相同的,但同样,一些常识是有序的:人们很难指望标准库是用你的项目中使用的预处理器符号编译的(像MYPROG_CONFIG_FILE_LOCATION这样的东西,说)。另一方面,请注意_GLIBCXX_DEBUG_GLIBCXX_DEBUG_PEDANTIC的预处理器定义将影响二进制兼容性(尽管g ++确保您将获得一个与它们一起使用的库版本,如果您一致地使用它们)。

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


3
投票

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

不是。

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

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

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

对。

这会以某种方式使用不同的语言方言选项编译更大项目的不同部分是否可以接受?

对于海湾合作委员会,是的,绝对。作为证明,没关系,考虑到libstdc++.so本身包含一些用-std=c++98构建的对象和一些用-std=c++14构建的对象。

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

不是在两个方向上,您需要使用GCC 4.6(或更新版本)中的libstdc++.so,因为使用该版本编译的对象可能依赖于较新版本中引入的符号,而不存在于较旧的libstdc++.so库中。

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


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

© www.soinside.com 2019 - 2024. All rights reserved.