Visual Studio 版本之间的 C++ 二进制兼容性(ABI)

官网链接:

https://learn.microsoft.com/en-us/cpp/porting/binary-compat-2015-2017?view=msvc-170

Visual Studio 版本之间的 C++ 二进制兼容性

文章
2025年1月31日
9 位贡献者

在本文中

  • 二进制兼容性的限制
  • 从 Visual Studio 2015 及更高版本升级 Microsoft Visual C++ Redistributable
  • 另请参阅

Visual Studio 2013 及更早版本中的 Microsoft C++ (MSVC) 编译器工具集不保证跨主要版本的二进制兼容性。您不能链接由这些工具集的不同版本构建的对象文件、静态库、动态库和可执行文件。ABI(应用程序二进制接口)、对象格式和运行时库是不兼容的。

我们在 Visual Studio 2015 及更高版本中更改了此行为。由这些编译器版本中的任何一个编译的运行时库和应用程序都是二进制兼容的。这反映在 C++ 工具集的主版本号上,自 Visual Studio 2015 以来,所有版本的主版本号都以 14 开头。(工具集版本:Visual Studio 2015 为 v140,2017 为 v141,2019 为 v142,2022 为 v143)。假设您有由 Visual Studio 2015 构建的第三方库。您仍然可以在由 Visual Studio 2017、2019 或 2022 构建的应用程序中使用它们。无需使用匹配的工具集重新编译。最新版本的 Microsoft Visual C++ Redistributable 包(可再发行组件包)适用于所有这些版本。

二进制兼容性的限制

v140、v141、v142 和 v143 工具集以及次要版本更新之间的二进制兼容性存在三个重要限制:

  1. 使用不同版本的 v140、v141、v142 和 v143 工具集创建的二进制文件可以组合使用。关键规则是链接器应该只处理由与其自身版本相同(或更早)的工具集构建的输入。 这适用于应用程序、导入库、静态库以及 LINK 输入文件中描述的其他文件。在某些情况下,由较新版本的工具集构建的隐式链接 DLL 的导入库可以使用较早版本的工具集进行链接——特别是如果导入库严格使用 extern "C" 进行导入/导出。以下是一些示例说明:

    • 使用 2017 工具集(v141,版本 15.0 到 15.9)编译的应用程序可以链接到使用 Visual Studio 2022 版本 17.8(v143)编译的静态库,但链接必须使用版本 17.8 或更高版本的工具集完成。
    • 使用 VS 2015、2017、2019 或 2022 构建的应用程序和库可以一起链接,但链接必须使用与用于构建传递给链接器的任何二进制文件的最新工具集一样新或更新的工具集版本来完成。例如,给定三个分别使用 VS 2015 版本 14.3、VS 2017 版本 15.9 和 VS 2019 版本 16.11 的工具集构建的二进制文件,您可以使用 16.11 或更高版本的任何工具集来链接它们。
    • 如果 DLL 是使用较新的工具集构建的,则如果所有导出都遵循 C 语言调用约定 (extern "C"),则导入库有时可以与较旧的工具集一起使用。但是,唯一官方支持的情况是使用较旧的工具集来使用较新的 Windows SDK。
  2. 您的应用程序使用的可再发行组件包具有类似的二进制兼容性限制。 当您混合使用不同受支持版本的工具集构建的二进制文件时,可再发行组件包的版本必须至少与任何应用程序组件使用的最新工具集一样新。

  3. 使用 /GL (整个程序优化) 编译器开关编译或使用 /LTCG (链接时代码生成) 链接的静态库或对象文件在版本之间(包括次要版本更新)不具备二进制兼容性。 所有使用 /GL/LTCG 编译的对象文件和库都必须为编译和最终链接使用完全相同的工具集。例如,在 Visual Studio 2019 版本 16.7 工具集中使用 /GL 构建的代码不能链接到在 Visual Studio 2019 版本 16.8 工具集中使用 /GL 构建的代码。编译器会发出致命错误 C1047。

从 Visual Studio 2015 及更高版本升级 Microsoft Visual C++ Redistributable

对于 Visual Studio 2015、2017、2019 和 2022,我们保持了 Microsoft Visual C++ Redistributable 主版本号相同。这意味着一次只能安装一个可再发行组件包的实例。较新版本会覆盖任何已安装的旧版本。例如,一个应用程序可能安装了来自 Visual Studio 2015 的可再发行组件包。然后,另一个应用程序安装了来自 Visual Studio 2022 的可再发行组件包。2022 版本会覆盖旧版本,但由于它们是二进制兼容的,因此较早的应用程序仍然可以正常工作。我们确保最新版本的可再发行组件包具有所有最新的功能、安全更新和错误修复。因此,我们始终建议您升级到最新的可用版本。

同样,当已安装较新版本时,您无法安装较旧的可再发行组件包。如果您尝试这样做,安装程序会报告错误。如果您在已安装 2022 版本可再发行组件包的计算机上安装 2017 或 2019 版本,您会看到类似这样的错误:

输出

0x80070666 - 本产品的另一个版本已安装。无法继续安装此版本。要配置或删除本产品的现有版本,请使用控制面板上的“添加/删除程序”。

此错误是设计使然。我们建议您保持安装最新版本。请确保您的安装程序可以静默地从此错误中恢复。

重要

最新版本的 Visual C++ Redistributable for Visual Studio不再提供对 Windows XP 的运行时库支持。最后一个支持 Windows XP 的可再发行组件包是版本 16.7(文件版本 14.27.29114.0)。如果您的 Windows XP 应用程序部署了或更新到更高版本的可再发行组件包,这些应用程序将无法运行。有关更多信息以及如何获取支持 Windows XP 的可再发行组件包版本,请参阅配置 Windows XP 程序。

另请参阅

  • Visual C++ 更改历史记录
  • 最新支持的 Visual C++ 可再发行组件包下载
  • 如何审查 Visual C++ 运行时版本的使用情况
  • 生命周期常见问题解答 - Visual C++ Redistributable 和运行时库

微软将 Visual Studio 2015、2017、2019 和 2022 的 C++ 运行时库打包到同一个Microsoft Visual C++ Redistributable包中(例如,Microsoft Visual C++ 2015-2022 Redistributable),这本身就强烈地表明了这些版本之间的二进制兼容性意图和实现。

这种做法的含义和印证:

  1. 共享的运行时 DLLs

    • 这个统一的可再发行组件包安装的运行时 DLL(如 msvcp140.dll, vcruntime140.dll, ucrtbase.dll 等)被设计为能够服务于由 VS2015 到 VS2022 任何一个版本编译的应用程序。
    • 文件名中的 140 (如 msvcp140.dll) 是一个关键。尽管 Visual Studio 的工具集版本从 v140 (VS2015) 演进到 v141 (VS2017)、v142 (VS2019) 和 v143 (VS2022),但核心的 C++ 运行时 DLL 的主版本号(通常体现在文件名上)保持了 140 这个基线。这表示它们在接口和行为上是向后兼容的。
  2. 一次安装,服务多个版本

    • 用户只需要安装最新版本的 Microsoft Visual C++ 2015-2022 Redistributable,理论上就可以运行所有使用这些 VS 版本(并动态链接运行时)编译的程序。
    • 如果系统中已经安装了较旧版本的(比如 2015-2019 的),安装最新的 2015-2022 版本会将其覆盖(升级),并且由于二进制兼容性,之前依赖旧版本的程序仍然可以正常工作。
  3. 简化部署

    • 对于开发者和用户来说,这大大简化了依赖管理和部署。不需要为每个 VS 版本追踪和安装完全独立的运行时包。
  4. ABI 稳定性的体现

    • 如果这些版本的 ABI 不兼容,那么一个统一的运行时包是无法正常工作的。例如,如果 std::string 在 VS2015 和 VS2022 中的二进制布局完全不同,那么一个共享的 msvcp140.dll 内部处理 std::string 的代码就会对其中一个版本产生错误。
    • 统一的运行时意味着传递像 std::vectorstd::string 这样的标准库对象,或者进行异常处理、内存分配等操作,都可以通过这套共享的、兼容的运行时机制来完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七贤岭↻双花红棍↺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值