为什么/Wp64被弃用了?

15

为什么Visual C++中的/Wp64标志被弃用

cl : 命令行警告 D9035:
选项'Wp64'已被弃用,并将在今后的版本中删除

4个回答

17
我认为/Wp64被弃用主要是因为编译64位目标会捕获它设计用于捕获的错误(/Wp64仅在32位编译中有效)。该选项是在64位目标出现时添加的,以帮助人们将其程序迁移到64位并检测不符合“64位规范”的代码。

这里有一个关于 /Wp64问题类型的示例,微软可能没有兴趣修复它——也许是正确的(来自http://connect.microsoft.com/VisualStudio/feedback/details/502281/std-vector-incompatible-with-wp64-compiler-option):

实际上,STL并非有意与/Wp64不兼容,也不完全和无条件地与/Wp64不兼容。根本问题是/Wp64与模板交互极差,因为__w64未完全集成到类型系统中。因此,如果vector<unsigned int> 实例化之前实例化了vector<__w64 unsigned int>,那么它们两者都将像vector<unsigned int>一样运行,反之亦然。在x86上,SOCKET__w64 unsigned int的typedef。这不明显,但实际上vector<unsigned int>在您的vector<SOCKET>之前被实例化了,因为我们的实现中vector<bool>是由vector<unsigned int>支持的。

以前(在VC9及更早版本中),/Wp64和模板之间的这种糟糕交互会导致虚假警告。然而,在VC10中,STL的变化使情况变得更糟。现在,当vector::push_back()接受了一个值时,它将尝试调用vector::insert(),从而捕获到/Wp64与模板的交互形成的问题。

当向量的一个元素被使用时,它会首先计算该元素在向量中的索引,然后再进行其他操作。这个索引是通过将该元素的地址减去向量开头的地址得到的。在您的示例中,这涉及到减去 const SOCKET * - unsigned int *。(由于之前描述的错误,后者是 unsigned int * 而不是 SOCKET *)。这可能会触发虚假警告,指出“我正在从 x86 上指向相同类型的指针中减去指向 x64 上不同类型的指针”。然而,这里存在第二个错误,/Wp64 会非常困惑,认为这是一个严重错误(同时将 const 加入到 unsigned int * 中)。
我们同意,这个错误信息很令人困惑。然而,由于它在不可静音的命令行弃用警告 D9035 之前,我们认为已经足够了。D9035 已经说过不应该使用 /Wp64(尽管它没有继续说“这个选项现在非常有缺陷,完全没有必要”)。
在 STL 中,我们可以在使用 /Wp64 时发出 #error。然而,这将破坏仍在使用 /Wp64(尽管有弃用警告)且未触发此虚假错误的客户端。STL 还可以发出警告,但编译器已经在发出 D9035。

事实上是错误的:“为64位目标编译将捕获它设计用于捕获的错误(/Wp64仅在32位编译中有效)”... 在VS2010 / SP1上,如果您想要获得C4311(这确实非常有帮助),则必须在x64构建中指定/Wp64。user13251在他的答案中也提到了这一点。 - Martin Ba

4
/Wp64在32位编译中是浪费时间的。它已被弃用,这种弃用是有道理的。在32位构建中,/Wp64的工作方式是查找类型上的_w64注释。这个_w64注释会告诉编译器,即使这个类型在32位模式下是32位,但在64位模式下是64位。这证明是非常不可靠的,特别是涉及到模板时。
/Wp64在64位构建中非常有用。文档(http://msdn.microsoft.com/en-us/library/vstudio/yt4xw8fh.aspx)声称它在64位构建中默认开启,但事实并非如此。只有在显式设置/Wp64时,编译器警告C4311和C4312才会被发出。这两个警告指示将32位值放入指针或反之的情况。这对于代码正确性非常重要,并声称为警告级别1。我发现在非常广泛的代码中发现了错误,如果开发人员为64位构建打开/Wp64,则可以防止这些错误。不幸的是,您还会收到您观察到的命令行警告。我不知道有什么方法可以消除这个警告,我已经学会了忍受它。好的一面是,如果您使用警告作为错误进行构建,则此命令行警告不会变成错误。

您可以通过类似 /w44311 /w44312 的选项启用这些警告,而不必使用 /Wp64。文档有误导之处,实际是指这些警告是由 /Wp64 启用的,而不是只有在启用 Wp64 时才能启用它们。可悲的是,没有“通常仅在启用 /Wp64 时启用”的警告列表,并且它们不会出现在“默认未开启的警告”列表中,因此我们只能在 MSDN 上寻找它们 :( - Ben Hymers
据我所知,在VS2010中,即使是在x64构建上,获得C4311唯一方法是指定/Wp64。我认为user13251的建议很好。(在我的VS2010上,/w44311不起作用,相应的pragma warning也不行)@BenHymers - Martin Ba
@MartinBa - 很好的信息,谢谢!我不记得我在2014年使用的编译器是什么,但我想它应该与我在VS2012或VS2013中描述的方式相同... :) 希望2014年的我没有在胡说八道! - Ben Hymers
@Ben 我猜考虑到文档的更改,我认为他们肯定已经解决了这个问题。 - Martin Ba

2

错误的。至少对于VS2010是这样的。文档有问题。 - Martin Ba

0

你可以链接到弃用警告,但不能进入 /Wp64 文档吗?

默认情况下,Visual C++ 32 位编译器中关闭 /Wp64 编译器选项,在 Visual C++ 64 位编译器中打开。

如果您经常使用 64 位编译器编译应用程序,则可以在 32 位编译中禁用 /Wp64,因为 64 位编译器将检测到所有问题。

已添加强调部分


所以他们只是因为它不是100%可靠就将其弃用了吗?我想必须实际上有一些问题,而不仅仅是它不能检测到所有问题(就像64位编译器也不能检测到所有问题一样)... - user541686
@Mehrdad - 他们正在废弃它,因为64位编译器无论如何都会执行相同的工作,而且是非可选的。 - Damien_The_Unbeliever
也许只是我个人的感觉,但我并不觉得那很有说服力,抱歉。 - user541686

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接