【问题标题】:GCC vs MS C++ compiler for maintaining API backwards binary compatibility用于维护 API 向后二进制兼容性的 GCC 与 MS C++ 编译器
【发布时间】:2011-01-24 13:46:53
【问题描述】:

我来自 Linux 世界,知道很多关于维护用 C++ 语言编写的动态库 API 的向后二进制兼容性 (BC) 的文章。其中之一是基于Itanium C++ ABI"Policies/Binary Compatibility Issues With C++",由GCC 编译器使用。但我找不到与 Microsoft C++ 编译器(来自 MSVC)类似的东西。

我了解大多数技术适用于 MS C++ 编译器,我想发现与 ABI 差异(v-table 布局、修改等)相关的编译器特定问题

所以,我的问题如下:

  • 在维护 BC 时,您知道 MS C++ 和 GCC 编译器之间的区别吗?
  • 在哪里可以找到有关 MS C++ ABI 或在 Windows 中维护 API BC 的信息?

任何相关信息将不胜感激。
非常感谢您的帮助!

【问题讨论】:

  • 无论您使用哪种编译器,这看起来都是不错的建议。实际上,文本说“此文本适用于可以构建 KDE 的编译器使用的大多数 C++ ABI。”并且还提到了 MSVC ABI 信息的来源 - 所以这很可能已经涵盖了 MSVC ABI。
  • 好问题 - 但 API 和 ABI 的混合似乎不清楚。标题和文本都可以进行编辑;当我认为它至少应该引用二进制兼容性时,标题没有对 ABI 发表评论。
  • @Rup - 它们也被注明:it's the most complete information found so far on MSVC ABI and name manglingsome of the constraints specified here may not apply to a given compiler。我想发现特定于编译器的问题。
  • @sdg - 我已将标题更改为更具体的二进制文件。
  • 嗯,我能让你停止编辑这个问题的标签的唯一方法是锁定它,或者锁定你。我不想搞砸你的赏金,所以...编辑一个帖子 17 次来修改它通常会导致帖子最终归社区所有,所以你可能不想在非赏金问题上尝试这种俗气。跨度>

标签: c++ visual-c++ gcc backwards-compatibility itanium-abi


【解决方案1】:

首先,这些策略是通用的,不仅仅指 gcc。例如:函数中的私有/公共标记是 MSVC 特有的,而不是 gcc。

所以基本上这些规则完全适用于 MSVC 和通用编译器。

但是……

你应该记住:

  1. GCC/C++ 自 3.4 版本以来一直保持其 ABI 稳定,大约 7 年(自 2004 年以来),而 MSVC 在每个主要版本中都会破坏其 ABI:MSVC8 (2005)、MSVC9 (2008)、MSVC10 (2010) 不兼容彼此。
  2. 与 MSVC 一起使用的一些常用标志也会破坏 ABI(如异常模型)
  3. MSVC 的调试和发布模式运行时不兼容。

所以是的,您可以使用这些规则,但与 MSVC 的通常情况一样,它有更多的怪癖。

另请参阅“Some thoughts on binary compatibility”,Qt 也使它们的 ABI 与 MSVC 保持稳定。

请注意,我在这方面有一些经验,因为我在 CppCMS 中遵循这些规则

【讨论】:

  • 出于我的好奇:MSVC ABI 在不同版本中发生了哪些变化?我还没有看到,除了运行时库之外我想不出任何其他东西(如果你小心的话,你可以解决这个问题)。
  • @Rup - 是的,运行时不兼容,默认值已更改,例如在 MSVC7 和 MSVC8 之间 wchar_t 的默认含义已更改,等等。所以基本上,混合使用不同编译器版本编译的库是非常糟糕的主意。
  • 你的回答很好,但是我希望得到更多的答案,因为我目前的工作是基于这个编程领域的。我打算今天开始赏金。
【解决方案2】:

在 Windows 上,您基本上有 2 个选项来实现长期二进制兼容性:

  1. COM
  2. 模仿 COM

在这里查看我的帖子。在那里,您将看到一种在不同编译器和编译器版本之间以二进制兼容的方式创建 DLL 和访问 DLL 的方法。

C++ DLL plugin interface

【讨论】:

    【解决方案3】:

    MSVC 二进制兼容性的最佳规则是使用 C 接口。根据我的经验,唯一可以摆脱的 C++ 特性是单继承接口。因此,将所有内容都表示为使用 C 数据类型的接口。

    这是一个二进制兼容的东西的列表:

    • STL。二进制格式甚至会在调试/发布之间发生变化,并且取决于编译器标志,因此最好不要使用 STL 跨模块。
    • 堆。不要在一个模块中 new / malloc 和在另一个模块中 delete / free。有不同的堆彼此不知道。 STL 不能跨模块工作的另一个原因。
    • 例外。不要让异常从一个模块传播到另一个模块。
    • 来自其他模块的 RTTI/dynamic_casting 数据类型。
    • 不要相信任何其他 C++ 功能。

    简而言之,C++ 没有一致的 ABI,但 C 有,因此请避免 C++ 功能跨模块。因为单继承是一个简单的 v-table,您可以有用地使用它来公开 C++ 对象,前提是它们使用 C 数据类型并且不进行跨堆分配。这也是微软自己使用的方法,例如对于 Direct3D API。 GCC 可能有助于提供稳定的 ABI,但标准并不要求这样做,而 MSVC 充分利用了这种灵活性。

    【讨论】:

    • 如果您考虑到 SECURE_SCL 和 HAS_ITERATOR_DEBUGGING 等潜在的恐怖因素来引入进一步的二进制不兼容性,MSVC C++ 看起来会更糟。
    • 是的,这是“取决于编译器标志”的一部分,也是您不能信任 ABI 的另一个原因。
    • 我正在寻找“基本 COM”一书中概述的 ABI 兼容性的简短答案。这看起来很接近。
    • @timday 他们为什么这么恐怖?你用过这些功能吗?
    • @0fnt:是的,虽然现在已经有好几年了(当时这个问题很活跃)。对于小规模开发,它们很好而且有用,但是当一个团队试图使用另一个团队生产的库时,它们只会给大规模开发带来麻烦:一些团队更喜欢“纯粹”的方法,而另一些团队则没有注意到,只是放弃了启用它们的 MSVC 默认值。最终通过一项组织范围内的协议解决了这一混乱,即从构建中删除此类额外内容以进行分发。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 2015-09-12
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    相关资源
    最近更新 更多