使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告

Using dynamically-allocated arrays causes spurious C6386 Buffer Overrun warning from Code Analysis

本文关键字:缓冲区 警告 溢出 C6386 数组 动态分配 代码      更新时间:2023-10-16

(注意:此问题与代码分析中错误的虚假C6386警告有关。它不是询问该警告的真实实例的问题的重复(

当我在C++中使用动态分配的数组时,我会收到Visual Studio 2019代码分析发出的虚假C6386警告。

这里有一个最小的可复制示例:

#include <vector>
int main()
{
std::vector<int> someInts{ 1, 2, 3 };
int* dynamicInts = new int[someInts.size()];
for (size_t i = 0; i < someInts.size(); i++)
{
dynamicInts[i] = someInts[i];
}
delete[] dynamicInts;
}

这里的意图是,我们有一个int向量,出于某种原因,我们希望将它们复制到一个动态分配的int数组中。(这个例子有点傻,但它说明了问题(。

请注意,在分配dynamicInts数组AND期间,代码使用someInts向量的size()作为循环的上限,因此永远不会出现缓冲区溢出的问题

然而代码分析生成:

main.cpp(11): warning C6386: Buffer overrun while writing to 'dynamicInts':  the writable size is 'someInts.public: unsigned int __thiscall std::vector<int,class std::allocator<int> >::size(void)const ()*4' bytes, but '8' bytes might be written.

错误列表中的详细解释将其解释为:

7: 'dynamicInts' is an array of 1 elements (4 bytes)
9: Enter this loop. (assume 'i<someInts.size()')
9: 'i' may equal 1
9: Continue this loop. (assume 'i<someInts.size()')
11: 'i' is an In/Out argument to 'std::vector<int,std::allocator<int> >::[]'
11: Invalid to write to 'dynamicInts[1]'. (writable range is 0 to 0)

这些消息表明分析器认为dynamicsInts阵列只是一个元素。

这似乎很奇怪。我知道"代码分析很难">但分析器肯定拥有它所需要的所有信息,就在那里推导数组长度和循环边界?

那么,这只是代码分析中的一个假阴性吗?还是我错过了什么?

如果它是一个假阴性,那么在不添加抑制并假设我们需要坚持使用动态分配的数组的情况下,避免此警告的最佳方法是什么?

有趣的是,我可以通过为数组的大小引入一个毫无意义的中间变量来消除警告,如下所示:

#include <vector>
int main()
{
std::vector<int> someInts{ 1, 2, 3 };
size_t numberOfInts = someInts.size();
int* dynamicInts = new int[numberOfInts];
for (size_t i = 0; i < numberOfInts; i++)
{
dynamicInts[i] = someInts[i];
}
delete[] dynamicInts;
}

我不知道为什么代码分析器喜欢这个,但不喜欢原始代码。

如果我使用智能指针来保存动态分配,Analyser也会很高兴,这有点整洁,可能是最初应该写的方式。

#include <vector>
#include <memory>
int main()
{
std::vector<int> someInts{ 1, 2, 3 };
std::unique_ptr<int[]> dynamicInts(new int[someInts.size()]);
for (size_t i = 0; i < someInts.size(); i++)
{
dynamicInts[i] = someInts[i];
}
}