你能混合使用同一编译器的不同版本编译的c ++吗?

时间:2014-05-27 17:03:31

标签: c++ gcc abi gcc4.9 gcc4.6

例如,我可以将一组已编译成GCC-4.6的库与GCC-4.9混合使用。

我知道不同的编译器“品种”如VS不能与MinGW一样,但是可以使用相同编译器的不同代吗?问题可能会发生吗?如果是这样的话?

2 个答案:

答案 0 :(得分:22)

同一编译器的不同代有时可以彼此兼容,但并非总是如此。例如,GCC 4.7.0 changed its C/C++ ABI,意味着用4.7.0+和4.7.0编译的库不太可能彼此兼容(因此在您的示例中,使用4.6编译的库将与4.9)编译的库兼容。在给定的编译器版本as happened in GCC 4.7.0/4.7.1中也可能存在ABI错误:

  

GCC版本4.7.0和4.7.1对C ++标准库进行了更改,这些库在C ++ 11模式下影响了ABI:数据成员被添加到std :: list中,改变了它的大小并改变了某些成员的定义函数和std :: pair的移动构造函数是非平凡的,它改变了使用std :: pair参数或返回类型的函数的调用约定。对于GCC版本4.7.2,已修复ABI不兼容性,但因此使用GCC 4.7.0或4.7.1编译的C ++ 11代码可能与使用不同GCC版本和C ++编译的C ++ 11代码不兼容用任何版本编译的98 / C ++ 03代码。

The GCC ABI Policy and Guidelines page表示他们尝试保持向前兼容性,但不支持向后兼容性:

  

版本控制为库二进制文件的后续版本提供了添加新符号和添加功能的能力,同时保留了与该系列中以前版本的兼容性。因此,如果库二进制文件被精心管理的后续库二进制文件替换,则与库二进制文件的初始版本链接的程序二进制文件仍将正确运行。这称为向前兼容性。

     

反向(向后兼容性)不正确。在发布系列中添加与最新版本的库二进制文件链接的程序二进制文件(添加了附加符号),在库二进制文件的初始版本中替换,并保持链接兼容。

该页面对GCC用于标记给定组件的不同版本的版本控制系统有一些相当冗长的解释,以及对GCC本身背后的版本控制的解释:

  

允许更改

     
      
  • 以下将导致库次要版本号增加,例如从“libstdc ++。so.3.0.4”增加到“libstdc ++。so.3.0.5”。

  •   
  • 添加导出的全局或静态数据成员

  •   
  • 添加导出的函数,静态或非虚拟成员函数

  •   
  • 通过其他实例化添加导出的符号

  •   
  • 可以进行其他允许的更改。

  •   
     

禁止更改

     

以下非详尽列表将导致库主版本号增加,例如从“libstdc ++。so.3.0.4”增加到“libstdc ++。so.4.0.0”。

     
      
  • gcc / g ++编译器ABI中的更改

  •   
  • 更改导出符号的大小

  •   
  • 更改导出符号的对齐

  •   
  • 更改导出符号的布局

  •   
  • 更改导出符号的修改

  •   
  • 删除导出的符号

  •   
  • 通过添加或删除基类来更改类型的继承属性

  •   
  • 更改C ++标准中指定的类型的大小,对齐方式或布局。这些可能不一定在库二进制文件中实例化或以其他方式导出,并包括所有必需的语言环境方面,以及std :: basic_streambuf等等。

  •   
  • 将显式复制构造函数或析构函数添加到否则将具有隐式版本的类中。这将改变编译器在按值返回语句或参数中处理此类的方式:不是在寄存器中传递此类的实例,编译器将被强制使用内存。有关详细信息,请参阅有关C ++ ABI文档的函数调用约定和API的部分。

  •   

注意粗体位。在完美的世界中,具有相同主要版本号的GCC版本将是二进制兼容的。这不是一个完美的世界,所以在你混合这样的编译器版本之前要非常仔细地测试,但一般来说你可能没问题。

答案 1 :(得分:3)

如果它们与ABI(应用程序二进制接口)兼容,则只能混合来自不同编译器的生成二进制文件或同一编译器的不同版本。

类似的事情:

  • 致电程序
  • 名称修改
  • 线程本地存储处理

都是ABI的一部分。

如果其中一项发生变化,您会发现链接器错误,崩溃或其他形式的意外行为。 作为一般规则,编译器供应商通常会尝试至少保持与旧版本的向后兼容性,但不能保证这一点。正如其他人所说,您必须阅读文档或重新编译所有内容。