如何避免 MSVC 警告 C4701:可能未初始化的局部变量

Posted

技术标签:

【中文标题】如何避免 MSVC 警告 C4701:可能未初始化的局部变量【英文标题】:How to avoid MSVC warning C4701: potentially uninitialised local variable 【发布时间】:2018-10-22 17:59:43 【问题描述】:

我有一些跨平台代码,我已将其精简为:

int bar(char **p) 
    *p = "hello";
    return 1;

void foo(int n) 
    int x = 0;
    char *p;
    if (n) x = bar(&p);
    if (x) if (p) return;

用 GCC 7 编译它不会给出警告。用 MSVC 编译它会给出两个警告:

$ gcc -Wall -Wextra -c foo.c
$ cl /Wall /c foo.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.15.26730 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

foo.c
c:\cygwin64\home\kyz\foo.c(9) : warning C4701: potentially uninitialized local variable 'p' used
c:\cygwin64\home\kyz\foo.c(9) : warning C4703: potentially uninitialized local pointer variable 'p' used

如果n 不为零,则初始化p。如果n 为零,则p 不会被初始化,但if (x)x 的默认零值确保永远不会达到if (p)

如何告诉 MSVC 在不更改编译器警告级别或将 p 初始化为虚拟值的情况下抑制这种情况?

FWIW,我 reported this to Microsoft,也许他们会在未来的编译器中修复它。这是一个棘手的问题,they're in good company

【问题讨论】:

也许这不是你的真实代码,但我建议if (x && p) return; 而不是if (x) if (p) return; 我知道这是一个简化的例子,但我不明白为什么NULL 是一个“虚拟值”。我想说,这个警告也不是没有道理的。从现在起 6 个月后,有人,甚至可能是您自己,以一种破坏您真正功能的方式更改 bar 例子是从this缩减的。我希望可证明的 use-before-initialisation 编译失败,但我不希望“潜在地”use-before-initialisation 误报。初始化p 将抑制所有使用前初始化分析。 【参考方案1】:

除非输入if (n),否则编译器不会看到无法输入if (x),在这种情况下,p 是通过函数调用分配给的。

大多数编译器不会执行那么深入的分析(静态分析器的用途),因此它会看到p 的可能代码路径,无需初始化即可读取。

也许处理这个问题的最好方法是将p 的范围限制在它的使用位置:

void foo(int n) 
    int x = 0;
    if (n) 
        char *p;
        x = bar(&p);
        if (x && p) 
            return;
        
    

【讨论】:

或将p初始化为null【参考方案2】:

一个问题是n 可能为零(即由于像foo(0); 这样的调用)所以在这里

    if (n) x = bar(&p);
           ^^^^^^^^^^^ 
           Not executed if n is 0

bar 可能不会被调用。在这种情况下,p 在此处使用时将未初始化:

   if (x) if (p) return;
              ^
              Uninitialized if n is 0

因为编译器很可能不会跟踪 x 的实际值。

你可以这样做:

   char *p = NULL;

摆脱警告。

【讨论】:

x 被初始化为 0。坦率地说,我不明白这如何回答 OP 的问题。这个答案似乎完全忽略了问题的内容。【参考方案3】:

就我个人而言,我会将指针初始化为 NULL,然后继续我的生活。

如果您不想更改警告级别,或者在此处输入warning pragmas 将其隐藏,您可以在属性下全局更改它。

(properties)

(c/c++)

(advanced)

enter 4701;4703 in the "Disable specific warnings" area.

在代码中禁用 msvc in-line 中的警告:

// Save warning levels, and drop it to level 3 
#pragma warning (push, 3)

// turn two warnings off
#pragma warning (disable : 4701 4703)

// screwy code goes here

// restore original warning levels.
#pragma warning (pop)

内嵌警告很有用,可让您删除围绕 microsoft 包含文件的警告,然后将它们重新插入以供您自己的代码使用。

【讨论】:

你让我在“警告编译指示”。在 MSVC 的这些代码行中,我可以使用哪些警告编译指示来抑制此警告?

以上是关于如何避免 MSVC 警告 C4701:可能未初始化的局部变量的主要内容,如果未能解决你的问题,请参考以下文章

在 MSYS 环境中使用 MSVC 工具链(例如:CL.EXE)时,如何避免“未解析的外部符号 _mainCRTStartup”错误?

强制整数初始化为 0 msvc++

如何让 MSVC 将未初始化的数据放入 .bss?

如何避免 TypeScript 中出现虚假的“未使用参数”警告

C:警告:“withdrawal_amt”可能在此函数中未初始化使用

React Native with Context API 警告:“允许需要循环,但可能导致未初始化的值......”