当溢出实际上永远不会发生时,Visual Studio 会发出缓冲区溢出警告

问题描述

这是我的代码

void foo(int num) {
    int *pArr = (int *)malloc(num * sizeof(int));
    // allocate array of 'sale' structs for each region
    for (int i = 0; pArr != NULL && i < num; i++) {
        pArr[i] = 1;
    }
}

int main() {
    int num = 36;
    foo(num);
}

表达式 pArr[i] = 1; 发出 C6386 警告

警告 C6386 写入“pArr”时缓冲区溢出:可写 大小是 'num*sizeof(int)' 字节,但可能会写入 '8' 字节。

这很奇怪,因为 for 循环的迭代次数和头部数组的大小都取决于 num,因此实际上永远不会发生溢出。

然后有详细的解释:

i 可能等于 1
pArr 可能是 NULL(继续这个循环)
pArr 的无效写入,(超出其可写范围)

但这当然是视觉工作室的错误pArr 不能是 NULL,因为这是进入循环的条件。

如何清除此警告?
谢谢大家

解决方法

您可以进行简单的更改以不再收到 C6386 警告。您应该在尝试分配之前测试 num 的值。 C 语言标准有一个关于将大小 0 传递给 malloc() 的有趣声明。

7.22.3 内存管理函数

如果请求的空间大小为零,则行为为 实现定义:要么返回空指针以指示 一个错误,或者行为就像大小是一些非零值, 除了返回的指针不得用于访问 对象

POSIX 标准说了类似的话:

如果大小为 0,则:

应返回空指针,并且可以将 errno 设置为 实现定义的值,或

应返回指向已分配空间的指针。应用程序 应确保指针不用于访问对象。

Microsoft 的代码分析不会为此代码发出 C6386:

void foo(int num)
{
    if (num == 0) { // avoid passing 0 to malloc()
        return;
    }
    int *pArr = (int *) malloc(num * sizeof(int));
    // allocate array of 'sale' structs for each region
    for (int i = 0; pArr != NULL && i < num; i++) {
        pArr[i] = 1;
    }
}
,

出现问题是因为 VS 似乎无法推断如果 pArr 为 NULL 则循环将永远不会运行。用

替换你的代码
new Date().getTime().toString()

将解决您的问题并提高运行时效率。