不合逻辑的C6001警告:在Visual Studio中的C中使用未初始化的内存警告

时间:2019-12-08 17:59:35

标签: c struct malloc free

给出以下代码:

#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存储器实现自由行。我想念什么?

enter image description here

2 个答案:

答案 0 :(得分:4)

这在很大程度上是一个误报,即使在 MSVC 2019 中仍然存在。t.p 变量不可能被取消初始化。

事实上,如果没有被初始化为一个非空值,它就无法到达 free() 语句。但是,即使你允许编译器不知道 exit() 函数不会返回的可能性,这实际上是无关紧要的,无论它是否返回,结构仍然会被初始化为 something< /em> 并且,无论如何,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)
}

答案 1 :(得分:0)

几点:

  1. 有时可以通过将 malloc() 替换为 calloc() 来“处理”SAL 警告

a) 更精确(提供元素大小计数参数)-更好的分析器预测?

b) 不同的 API - 那个可能没有被检测,因此没有分析仪输出? ;-P

  1. 分析可能会通过该函数中的 exit() 混淆,这有点像与 [missing] noreturn 归因有关(这种情况非常类似于通过异常退出基于返回值的函数扔),见例如https://en.cppreference.com/w/cpp/language/attributes; OTOH noreturn 属性在这里是条件(即,不是在所有代码路径中),因此 noreturn 属性闻起来不精确/错误(代码正在试图使用函数结果毕竟)

  2. 通常,通过逐步删除(可能更大的)实现部分直到它开始“工作”,尝试积极地“打破”事物以实现“工作”无警告行为。例如。在这种情况下,删除 exit() 行可能会导致 SAL 行为发生变化,从而提供有关“问题”实际上是哪个方面的线索。

  3. 也许设计可能不如可能的最佳 - 在这种情况下,一些有限的返工可能会导致更“明显”/“优雅”/“现代”的处理,这可能导致不产生此类 SAL 警告。