我有一个使用VS2010 64位环境编译的工作应用程序 - 在尝试将其迁移到VS2012编译器(C ++ 11)时,我收到C6386警告并且似乎无法找到根本原因:
这是产生警告的代码片段:
Packet::Packet(const Packet& oOther)
{
m_vData.assign(oOther.m_vData.begin(),oOther.m_vData.end());
if(NULL != oOther.m_pValueChecks)
{
m_pValueChecks = new set<string>*[oOther.m_vData.size()];
for(size_t i = 0; i < oOther.m_vData.size(); ++i)
{
if(NULL == oOther.m_pValueChecks[i])
{
m_pValueChecks[i] = NULL;
}
else
{
/// compiler warns on the below line
m_pValueChecks[i] = new set<string>(oOther.m_pValueChecks[i]->begin(), oOther.m_pValueChecks[i]->end());
}
}
}
}
包类定义:
class Packet
{
public:
Packet();
Packet(const Packet&);
.....
vector<pair<string,pair<FieldType,Field> > > m_vData;
set<string> ** m_pValueChecks;
}
生成的警告:
c:\<my_path_and_file>(3331): warning C6386: Buffer overrun while writing to 'm_pValueChecks': the writable size is 'oOther.m_vData.public: unsigned __int64 __cdecl std::vector<struct std::pair<string,struct std::pair<enum Packet::FieldType,class Field> >,class std::allocator<struct std::pair<string,struct std::pair<enum Packet::FieldType,class Field> > > >::size(void)const ()*8' bytes, but '16' bytes might be written.: Lines: 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3322, 3323, 3325, 3331, 3323, 3325, 3331
由于编译环境为64位,oOther.m_vData.size()
的类型为size_t
,在64位环境中为64位无符号整数,因此for
循环在范围内正确迭代,m_pValueChecks
包含足够的已分配项目以满足分配。
为什么要生成警告?
答案 0 :(得分:1)
您似乎在一些地方混合了other.m_pValueChecks
和other.m_vData
。这可能会因阵列大小不匹配而导致内存损坏。
不要考虑这种可怕的双指针方法,而是考虑将你的设置放在另一个容器类型中,并让语言安全地为你完成所有这些。
答案 1 :(得分:0)
好的 - 继续深入研究场景 - 我发现该项目包含/ analyze开关,强制VS2012的Code Analysis选项始终运行。
删除此开关时,上面(讨厌的我同意)代码编译时没有任何警告。
现在,由于此特定代码在VS2010 64位环境中没有警告编译,因此VS2010与VS2012代码分析规则的差异是警告的主要嫌疑。
目前,我已经在我的迁移工作中通过了这个障碍,我将尝试继续理解规则之后的差异。如果有人可以对它进行遮挡,那么将它贴在这里会很棒。
修改强> 我发现Code Analyzer不能在VS2010上运行 - 编译器开关被忽略,这解释了为什么这个代码正在编译。无论如何都需要适当的重新考虑因素。
编辑2
人们经过深思熟虑(差不多6个月)后终于找到了根本原因......m_pValueChecks = new set<string>*[oOther.m_vData.size()];
for(size_t i = 0; i < oOther.m_vData.size(); ++i)
{
if(NULL == oOther.m_pValueChecks[i])
{
m_pValueChecks[i] = NULL;
}
else
{
/// commpiler warns on the below line
m_pValueChecks[i] = new set<string>(oOther.m_pValueChecks[i]->begin(), oOther.m_pValueChecks[i]->end());
}
}
原因是因为for
循环使用i
递增++i
索引,这意味着首先i
变量递增,然后被使用。
这意味着i
变量可能会超过oOther.m_vData.size()
m_pValueChecks
已分配数组的大小。
将for
floop更改为for(size_t i = 0; i < oOther.m_vData.size(); i++)
删除了警告。