当我在C ++中使用动态分配的数组时,我收到了Visual Studio 2019代码分析发出的C6386 warning。
这是一个最小的可重现示例:
#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;
}
这里的意图是我们有一个整数向量,出于某种原因,我们希望将它们复制到一个动态分配的整数数组中。 (有点愚蠢的例子,但它显示了问题)。
在分配size()
数组的过程中,它使用向量的dynamicInts
作为循环的上限,所以我看不到缓冲区溢出问题。
但是此代码会生成:
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
数组只是一个元素。
这似乎很奇怪。我知道“代码分析很困难”,但可以肯定的是,分析器在那里具有导出数组长度和循环边界所需的所有信息?
那么这只是代码分析的假阴性吗?还是我错过了什么?
如果它是一个假阴性,那么避免这种警告而不添加抑制并假设我们需要坚持动态分配数组的最佳方法是什么?
答案 0 :(得分:0)
有趣的是,我可以通过为数组的大小引入无意义的中间变量来消除警告,如下所示:
#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;
}
我不知道为什么代码分析器喜欢这个,但是不喜欢原始代码。
如果我使用智能指针来保存动态分配,那么分析器也很高兴,这有点整洁,而且很可能是应该首先编写它的方式。
#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];
}
}