这是 MSVC++ 2017 更新 3 中的编译器错误吗

Is this a compiler bug in MSVC++ 2017 update 3

#include <vector>

std::vector<int>::iterator foo();
void bar(void*) {}

int main()
{
    void* p;
    while (foo() != foo() && (p = 0, true))
    {
        bar(p);
    }
    return 0;
}

结果错误:

c:\users\jessepepper\source\repos\testcode\consoleapplication1\consoleapplication1.cpp(15): error C4703: potentially uninitialized local pointer variable 'p' used

这是一个错误,但对于您编写的代码类型来说非常典型。

首先,这不是错误,而是警告。 C4703 是 4 级警告(意味着默认情况下甚至不启用)。因此,为了将其报告为错误(从而中断编译),传递了编译器参数或编译指示以启用此警告并将其变成错误(/W4/Werror 最有可能是我想想)。

然后在编译器中有一个trade-off。数据流分析应该有多复杂才能确定变量是否实际上未初始化?它应该是过程间的吗?它越复杂,编译器就越慢(并且由于停止问题,这个问题可能无论如何都无法确定)。越简单,得到的误报就越多,因为保证初始化的条件太复杂,编译器无法理解。

在这种情况下,我怀疑编译器的分析是这样进行的:对 p 的赋值是在条件语句之后(仅当 foo() != foo() 时才会发生)。 p 的用法也在条件后面(只有当复合 and-expression 为真时才会发生)。编译器无法在这些条件之间建立关系(分析不够复杂,无法意识到 foo() != foo() 是整个 while 循环条件为真的前提条件)。因此,编译器错误地假设访问可以在没有事先初始化的情况下发生并发出警告。

所以这是一个工程trade-off。您可以报告错误,但如果您这样做,我建议您提供一个更有说服力的 real-world 惯用代码示例,以支持使分析更复杂。您确定不能重构您的原始代码以使其更易于编译器使用,同时更易于人类阅读吗?

我对 VC++2017 预览版进行了一些试验。

这绝对是一个 bug bug。它使得无法编译和 link 可能正确的代码,尽管有臭味。

警告是可以接受的。 (请参阅@SebastianRedl 的回答。)但在最新和最伟大的 VC++2017 中,它被视为错误,而不是警告,即使警告已关闭,并且 "Treat warnings as errors" 设置为否。奇怪的事情正在发生。 "error" 被延迟抛出 - 在它说 "Generating code" 之后。我猜想,这只是一个猜测,"Generating code" pass 正在进行全局分析以确定是否可以进行 un-initialized 访问,但它弄错了。即使那样,您也应该能够禁用错误,IMO。

我不知道这是不是新行为。阅读塞巴斯蒂安的回答,我想是的。当我收到任何级别的警告时,我总是在代码中修复它,所以我不知道。

杰西,点击Visual Studio右上角的三角旗,举报

这肯定是一个错误。我尝试以所有可能的方式删除它,包括#pragma。实际情况是,这被报告为错误,而不是像 Microsoft 所说的警告。这是微软的一个大错误。这不是警告,而是错误。请不要再重复这是一个警告,因为它不是。 我正在做的是尝试编译一些我不想以任何方式修复其源代码的第三方库,并且应该在正常情况下编译,但它不会在 VS2017 中编译,因为臭名昭著的 "error C4703: potentially uninitialized local pointer variable *** used"。 有人找到了解决方案吗?