不合逻辑的 C6001 警告:在 C 中使用未初始化的内存警告 Visual Studio
Unlogical C6001 warning: Using uninitialized memory warning in C with Visual Studio
鉴于此代码:
#include <stdlib.h>
typedef struct
{
int *p;
} MyStruct;
MyStruct Test()
{
MyStruct ms;
ms.p = malloc(sizeof(int) * 5);
if (!ms.p) exit(-1);
return ms;
}
int main(void)
{
while (1)
{
MyStruct t = Test();
free(t.p); // C6001: Using uninitialized memory 't.p'.
}
}
Visual Studio 在 free
调用行上显示 C6001 警告。但是,我看到没有办法在内存 t.p 未初始化的情况下实现空闲行。我错过了什么?
几点:
- 有时可以通过用 calloc() 替换 malloc() 来“处理”SAL 警告
a) 更精确(提供元素大小 和 计数参数)- 更好的分析器预测?
b) 不同 API - 那个可能没有检测,因此没有分析器输出? ;-P
分析可能会通过该函数中的 exit() 混淆,它闻起来有点像与 [missing] noreturn 属性有关(这种情况非常类似于摆脱return-通过异常抛出的基于值的函数),参见例如https://en.cppreference.com/w/cpp/language/attributes; OTOH noreturn 属性的东西在这里是 conditional(即,不是在所有代码路径中),因此 noreturn 属性闻起来 imprecise/wrong(代码 是 尝试使用函数结果)
通常,通过逐步删除(可能更大的)实现部分直到它开始“工作”,尝试积极地“破坏”事物以实现“工作”无警告行为。例如。在这种情况下,删除 exit() 行可能会导致 SAL 行为发生变化,从而提供有关实际是“问题”的方面的线索。
也许设计可能不够理想 - 在这种情况下,一些有限的返工可能会导致更“明显”/“优雅”/“现代”的处理,这可能会导致无法生产这样的 SAL 警告。
这是一个误报,即使在 MSVC 2019 中仍然存在。t.p
变量不可能未初始化。
事实上,如果不将其初始化为 非 NULL 值,它就无法到达 free()
语句。但是,即使你考虑到编译器不知道 exit()
函数不会 return 的可能性,这实际上是无关紧要的,无论是否 returns,结构都会仍然被初始化为 something 并且在任何情况下,free(NULL)
.
都是完全合法的
删除 if .. exit
对警告没有影响,所以我怀疑这就是问题所在。这更有可能只是 MSVC 积极报告警告,阻止它打扰你的最好方法就是简单地忽略它。
我不是说 你 忽略了警告(考虑到我的本性,我永远不会那样做),我的意思是告诉 MSVC 闭嘴:
while (1) {
MyStruct t = Test();
// MSVC wrongly reports this as using uninitialised variable.
#pragma warning(push)
#pragma warning(disable: 6001)
free(t.p);
#pragma warning(pop)
}
鉴于此代码:
#include <stdlib.h>
typedef struct
{
int *p;
} MyStruct;
MyStruct Test()
{
MyStruct ms;
ms.p = malloc(sizeof(int) * 5);
if (!ms.p) exit(-1);
return ms;
}
int main(void)
{
while (1)
{
MyStruct t = Test();
free(t.p); // C6001: Using uninitialized memory 't.p'.
}
}
Visual Studio 在 free
调用行上显示 C6001 警告。但是,我看到没有办法在内存 t.p 未初始化的情况下实现空闲行。我错过了什么?
几点:
- 有时可以通过用 calloc() 替换 malloc() 来“处理”SAL 警告
a) 更精确(提供元素大小 和 计数参数)- 更好的分析器预测?
b) 不同 API - 那个可能没有检测,因此没有分析器输出? ;-P
分析可能会通过该函数中的 exit() 混淆,它闻起来有点像与 [missing] noreturn 属性有关(这种情况非常类似于摆脱return-通过异常抛出的基于值的函数),参见例如https://en.cppreference.com/w/cpp/language/attributes; OTOH noreturn 属性的东西在这里是 conditional(即,不是在所有代码路径中),因此 noreturn 属性闻起来 imprecise/wrong(代码 是 尝试使用函数结果)
通常,通过逐步删除(可能更大的)实现部分直到它开始“工作”,尝试积极地“破坏”事物以实现“工作”无警告行为。例如。在这种情况下,删除 exit() 行可能会导致 SAL 行为发生变化,从而提供有关实际是“问题”的方面的线索。
也许设计可能不够理想 - 在这种情况下,一些有限的返工可能会导致更“明显”/“优雅”/“现代”的处理,这可能会导致无法生产这样的 SAL 警告。
这是一个误报,即使在 MSVC 2019 中仍然存在。t.p
变量不可能未初始化。
事实上,如果不将其初始化为 非 NULL 值,它就无法到达 free()
语句。但是,即使你考虑到编译器不知道 exit()
函数不会 return 的可能性,这实际上是无关紧要的,无论是否 returns,结构都会仍然被初始化为 something 并且在任何情况下,free(NULL)
.
删除 if .. exit
对警告没有影响,所以我怀疑这就是问题所在。这更有可能只是 MSVC 积极报告警告,阻止它打扰你的最好方法就是简单地忽略它。
我不是说 你 忽略了警告(考虑到我的本性,我永远不会那样做),我的意思是告诉 MSVC 闭嘴:
while (1) {
MyStruct t = Test();
// MSVC wrongly reports this as using uninitialised variable.
#pragma warning(push)
#pragma warning(disable: 6001)
free(t.p);
#pragma warning(pop)
}