Memcpy 可读范围

Memcpy Readable Range

小码位:

int main()
{
    char buf[18];
    char buf2[18];
    int newlength = 16;
    memset(buf, '0', 16);
    for (int i = newlength; i < 18; i++)
        buf[i] = 0x00;

    memcpy(buf2, buf, 18);

    return 0;
}

首先我想将数组的一部分设置为特定值,然后我想用 0x00 填充其余部分。然后我想把它复制到另一个数组。

在 MS VS2013 上,我收到警告,因为 buf 的可读范围在 0 到 15 之间。(C/C++ 警告的代码分析。C6385 读取溢出)为什么? memcpy 是否忽略设置为 0x00 的位?

似乎是编译器/lint 工具中的错误(取决于向您显示警告的人)

您正在初始化 16 个字节。您正在访问 18 个字节。它似乎认为访问正在读取,即使它不应该。

来自代码分析器的这条消息似乎是基于缓冲区内容将单独定义为 memset() 输出的原则。它错过了 memset() 之后的循环完成此输入的要点。

如果双击警告,您可以突出显示考虑触发此警告的行。

但是你写的代码是正确的,所以你不用担心这里的结果。在线文档说 "might" 没有 "will" :

This warning indicates that the readable extent of the specified buffer might be smaller than the index used to read from it.

补充说明:

当让分析器的情况更加明显时,它仍然会带来同样的辱骂性警告:

    memset(buf, '0', 16);
    memset(buf + 16, 0x00, 2);  // for replacing the loop

在这种情况下,分析器注意到第二个 memset()。但由于它从一开始就不会影响 buf,因此它作为 input/output 进行缓冲区操作而不考虑额外的长度。

即使是这种过于谨慎的代码也会引发警告:

    memset(buf, 0x00, sizeof(buf));   // completeky initalize the buffer
    memset(buf, '0', 16);             // overwrite just the beginning

这里,似乎一旦 memxxx() 操作以缓冲区的开头为目标,该操作的长度就被认为是唯一的初始化部分。

所以,是的,警告很烦人,但请相信您的代码。我只能通过编写非常奇怪的低效编码来消除警告:

    memset(buf, 0x00, sizeof(buf));   // 18 bytes get initalized
    memset(buf + 1, '0', 15);         // not begin of buffer 
    buf[0] = '0';                     // not a memxxx() operation 

不幸的是,分析器的配置不允许只禁用这条规则,而是整套安全验证规则。