首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

VS 17.5 预览版2:/Gw链接开关的标准一致性改进

/Gw 链接开关可以告诉链接器优化代码中的全局数据,从而减小最终生成的二进制文件的大小。在 Visual Studio 17.5 预览版2中,我们新增了一个新的标志:/Zc:checkGwOdr[-] ,目的是在使用 /Gw 开关的时候改进对 C++ 标准的一致性支持。

在之前的版本中,当使用 /Gw 开关的时候,某些单定义规则(ODR)冲突会被忽略,并且不会导致错误。有了这个新标志之后,如果发生这种情况的时候,VS 将会报告错误。如果你正在使用 /Gw,则我们推荐使用 /Zc:checkGwOdr 这个标志。默认情况下,这个标志是被关闭的。在将来的新版本 VS 中,我们可以改变这个默认设置。

如果你想了解关于ODR的解释,/Gw 开关,以及有关这个问题的更多信息,请继续阅读。

让我们来看看下面三个定义,先建立对这个问题的基本背景知识:

1. 首先是 COMDAT,简短的描述是 COMDAT 是可以放置数据的额外段,以使链接器能够潜在地从二进制文件中折叠出所述数据。重要的是,这些部分标有如何处理重复项的策略。有关 COMDAT 历史的更深入探讨,请参阅 Raymond 的博客文章,其中涵盖了它们的使用和历史。

2. 接下来,/Gw 开关是做什么的?该开关使编译器能够将全局数据放入 COMDAT 中。这使我们能够优化未引用的全局变量,或通过它们的 COMDAT 部分合并相同的全局变量。

3. 关于单定义规则(ODR),可以在网上找找相关的信息。

有了上面的背景知识,下面我们来看一个简单的例子:

如果不使用 /Gw 开关,编译上面的代码会产生如下的编译错误:

由于我们在 odr.h 中定义了 MyGlobal,因此我们最终在 foo.obj 和 bar.obj 中都有一个定义,导致链接器报告 ODR 违规。现在,如果我们使用 /Gw 编译:

我们最终没有出现错误,那么发生了什么?它最终回到上面提到的 COMDAT 标志。查看 obj 的头文件,我们可以看到 MyGlobal 确实被放置在 COMDAT 中:

这没有显示的是这个COMODAT已被标记为PICKANY。因此,当找到多个可以合并的候选定义时,链接器会任意选择其中一个并丢弃其余定义。不过这很奇怪,当启用 /Gw 时,此 COMDAT 在创建时被标记为 NOMATCH。NOMATCH,顾名思义,意味着如果找到重复项,链接器应该引发错误,这正是我们想要的。那么,出了什么问题呢?

这里的关键是MyGlobal的定义包括零赋值。这会导致另一个优化启动。由于此全局初始化为零,我们注意到它可以移动到 .bss 部分。由于如果此全局数据位于 .bss 中,则不必存储此全局数据,因此移动 COMDAT 可以减小对象文件大小。不幸的是,当我们移动COMCTAT时,标志从NOMATCH重置为PICKANY,导致我们的错误。

从 17.5 预览版 2 开始,你现在可以使用新标志来确保不会在意外使用 /Gw 时隐藏这些 ODR 违规:

暴露错误后,我们可以在头文件中创建全局 extern,并将定义移动到其中一个 cpp 文件以解决问题:

或者,对于 C++17 及更高版本,可以在定义上使用内联说明符 (inline specifier) 。

通常修复 ODR 违规看起来像这样,尽管并非每种情况都如此简单。如果你使用的是 /Gw,我们鼓励使用 /Zc:checkGwOdr,以防止这些冲突蔓延到你的构建中。由于这是一个标准一致性问题,我们可能会在未来的版本中更改 /Gw 的默认行为以暗示 /Zc:checkGwOdr。

总结

不知道你有什么想法,但我感觉这事儿有点按下葫芦 (/Gw) 浮起瓢 (/Zc:checkGwOdr)。

顺便说一句,Topomel Box 开发中,我压根没用过这些高级优化的劳什子玩意儿。

随它去吧。

最后

Microsoft Visual C++团队的博客是我非常喜欢的博客之一,里面有很多关于Visual C++的知识和最新开发进展。大浪淘沙,如果你对Visual C++这门古老的技术还是那么感兴趣,则可以经常去他们那(或者我这)逛逛。

本文来自:《Standards conformance improvements to /Gw in Visual Studio version 17.5 Preview 2》

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230112A03IUR00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券