为什么与依赖应用程序使用与动态库相同的编译器?

时间:2014-05-10 06:00:47

标签: c++ qt linkage abi

最近我不得不编译Qt并且说明清楚地提到我的应用程序应该使用与我编译Qt的编译器相同的编译器进行编译。 现在我不明白这个的原因,并想知道这是特定于Qt还是通用C ++的东西?

1 个答案:

答案 0 :(得分:4)

简介

  

使用不同编译器创建的对象文件和静态库,或者甚至使用相同编译器的显着不同版本创建的对象文件和静态库通常无法链接在一起。此问题并非特定于MinGW:许多其他编译器互不兼容。如果可以的话,使用相同版本的相同编译器从源代码构建所有内容。

     

Dll略有不同。有时您可以将使用一个编译器构建的DLL链接到使用另一个编译器编译的应用程如果DLL是用C语言编写的,即使应用程序是用C ++编写的,这也很有效。例如,MinGW C ++程序通常链接到Windows提供的C运行时库。用C ++编写的DLL也可以工作,只要你通过用extern“C”声明的C接口与它们通信即可。如果不这样做,您可能会遇到链接器错误,因为不同的编译器会以不同的方式破坏C ++名称。

为什么不同的编译器不能互操作

  

有时人们想知道为什么编译器编写者不只是使用相同的名称修改方案。这可能会使链接成功,但很可能会给你一个程序在你调用DLL时崩溃。真正的链接兼容性需要一个通用的应用程序二进制接口,并且名称修改只是众多中的一个考虑因素。以下是部分列表: -

如果同一系统的两个C ++实现使用不同的调用序列,或者在其他方面不兼容链接,则使用相同类型签名的编码是不明智的。

  

传统上传统上使用故意不同的名称修改方案,认为在链接时“只是说不”比使一些简单的代码工作更好,并让问题在运行时出现。

     

尽管GNU g ++现在可以链接MSVC C ++库,并且可以生成与MSVC ++兼容的库/ DLL,但这并不意味着由于C ++的动态特性,它们将能够在运行时工作。一些可能的原因是: -

  • 简单名称修改问题,可以通过显式.def文件来规避。
  • 需要正确编译器选项的不同结构对齐问题(-mms-bitfields,...)。
  • 潜在异常和内存模型的基本冲突: -

MSVC DLL中的new / delete或malloc / free不会与Cygwin newlib new / delete或malloc / free合作。一个人不能释放使用不同的new / malloc在函数中分配的空间。

MSVC DLL引发的异常不会被Cygwin可执行文件捕获,反之亦然。

缓慢的GNU SJLJ异常模型(在GCC-3.x及更早版本中使用)与MSVC ++模型兼容,但新的DWARF2模型(将由GCC-4.x使用)将是不兼容。

可以找到规范来源here