为什么Visual C++中的/Wp64
标志被弃用?
cl : 命令行警告 D9035:
选项'Wp64'已被弃用,并将在今后的版本中删除
/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 *
中)。/Wp64
(尽管它没有继续说“这个选项现在非常有缺陷,完全没有必要”)。/Wp64
时发出 #error。然而,这将破坏仍在使用 /Wp64
(尽管有弃用警告)且未触发此虚假错误的客户端。STL 还可以发出警告,但编译器已经在发出 D9035。/w44311 /w44312
的选项启用这些警告,而不必使用 /Wp64
。文档有误导之处,实际是指这些警告是由 /Wp64
启用的,而不是只有在启用 Wp64
时才能启用它们。可悲的是,没有“通常仅在启用 /Wp64
时启用”的警告列表,并且它们不会出现在“默认未开启的警告”列表中,因此我们只能在 MSDN 上寻找它们 :( - Ben HymersC4311
的唯一方法是指定/Wp64
。我认为user13251的建议很好。(在我的VS2010上,/w44311
不起作用,相应的pragma warning
也不行)@BenHymers - Martin Ba你可以链接到弃用警告,但不能进入 /Wp64
文档吗?
默认情况下,Visual C++ 32 位编译器中关闭 /Wp64 编译器选项,在 Visual C++ 64 位编译器中打开。
如果您经常使用 64 位编译器编译应用程序,则可以在 32 位编译中禁用 /Wp64,因为 64 位编译器将检测到所有问题。
已添加强调部分