如何避免 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”错误?
如何避免 TypeScript 中出现虚假的“未使用参数”警告