for循环中删除map中的元素valgrind检测提示error:Invalid read of size 8
废话不多说,先看下面一段代码
#include<iostream>
#include<map>
usingnamespacestd;
classA
{
public:
typedefstd::map<int,string>myMap;
voidmapInsert(inti,strings)
{
map.insert(std::make_pair(i,s));
}
voiddeleteMap()
{
for(myMap::iteratorit=map.begin();it!=map.end();++it)
{
map.erase(it->first);
}
}
private:
myMapmap;
};
intmain()
{
Aa;
a.mapInsert(1,"1");
a.mapInsert(2,"2");
a.mapInsert(3,"3");
a.mapInsert(4,"4");
a.mapInsert(5,"5");
a.deleteMap();
return0;
}
上述代码编译运行皆没有问题,但是用valgrind检测会提示错误:
valgrind--tool=memcheck--leak-check=full--track-origins=yes./test#~/test ==723953==Memcheck,amemoryerrordetector ==723953==Copyright(C)2002-2012,andGNUGPL'd,byJulianSewardetal. ==723953==UsingValgrind-3.8.1andLibVEX;rerunwith-hforcopyrightinfo ==723953==Command:./test ==723953== ==723953==Invalidreadofsize8 ==723953==at0x3431C69E60:std::_Rb_tree_increment(std::_Rb_tree_node_base*)(tree.cc:60) ==723953==by0x40131C:std::_Rb_tree_iterator<std::pair<intconst,std::string>>::operator++()(in/home/thm/test/test) ==723953==by0x40117C:A::deleteMap()(in/home/thm/test/test) ==723953==by0x400F4B:main(in/home/thm/test/test) ==723953==Address0x4c580b8is24bytesinsideablockofsize48free'd ==723953==at0x4A06016:operatordelete(void*)(vg_replace_malloc.c:480) ==723953==by0x401E23:__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<intconst,std::string>>>::deallocate(std::_Rb_tree_node<std::pair<intconst,std::string>>*,unsignedlong)(in/home/thm/test/test) ==723953==by0x401C99:std::_Rb_tree<int,std::pair<intconst,std::string>,std::_Select1st<std::pair<intconst,std::string>>,std::less<int>,std::allocator<std::pair<intconst,std::string>>>::_M_put_node(std::_Rb_tree_node<std::pair<intconst,std::string>>*)(in/home/thm/test/test) ==723953==by0x401AA6:std::_Rb_tree<int,std::pair<intconst,std::string>,std::_Select1st<std::pair<intconst,std::string>>,std::less<int>,std::allocator<std::pair<intconst,std::string>>>::_M_destroy_node(std::_Rb_tree_node<std::pair<intconst,std::string>>*)(in/home/thm/test/test) ==723953==by0x401729:std::_Rb_tree<int,std::pair<intconst,std::string>,std::_Select1st<std::pair<intconst,std::string>>,std::less<int>,std::allocator<std::pair<intconst,std::string>>>::erase(std::_Rb_tree_iterator<std::pair<intconst,std::string>>)(in/home/thm/test/test) ==723953==by0x40134C:std::map<int,std::string,std::less<int>,std::allocator<std::pair<intconst,std::string>>>::erase(std::_Rb_tree_iterator<std::pair<intconst,std::string>>)(in/home/thm/test/test) ==723953==by0x401170:A::deleteMap()(in/home/thm/test/test) ==723953==by0x400F4B:main(in/home/thm/test/test) ==723953== ==723953==Invalidreadofsize8 ==723953==at0x3431C69E80:std::_Rb_tree_increment(std::_Rb_tree_node_base*)(tree.cc:68) ==723953==by0x40131C:std::_Rb_tree_iterator<std::pair<intconst,std::string>>::operator++()(in/home/thm/test/test) ==723953==by0x40117C:A::deleteMap()(in/home/thm/test/test) ==723953==by0x400F4B:main(in/home/thm/test/test) ==723953==Address0x4c580a8is8bytesinsideablockofsize48free'd ==723953==at0x4A06016:operatordelete(void*)(vg_replace_malloc.c:480) ==723953==by0x401E23:__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<intconst,std::string>>>::deallocate(std::_Rb_tree_node<std::pair<intconst,std::string>>*,unsignedlong)(in/home/thm/test/test) ==723953==by0x401C99:std::_Rb_tree<int,std::pair<intconst,std::string>,std::_Select1st<std::pair<intconst,std::string>>,std::less<int>,std::allocator<std::pair<intconst,std::string>>>::_M_put_node(std::_Rb_tree_node<std::pair<intconst,std::string>>*)(in/home/thm/test/test) ==723953==by0x401AA6:std::_Rb_tree<int,std::pair<intconst,std::string>,std::_Select1st<std::pair<intconst,std::string>>,std::less<int>,std::allocator<std::pair<intconst,std::string>>>::_M_destroy_node(std::_Rb_tree_node<std::pair<intconst,std::string>>*)(in/home/thm/test/test) ==723953==by0x401729:std::_Rb_tree<int,std::pair<intconst,std::string>,std::_Select1st<std::pair<intconst,std::string>>,std::less<int>,std::allocator<std::pair<intconst,std::string>>>::erase(std::_Rb_tree_iterator<std::pair<intconst,std::string>>)(in/home/thm/test/test) ==723953==by0x40134C:std::map<int,std::string,std::less<int>,std::allocator<std::pair<intconst,std::string>>>::erase(std::_Rb_tree_iterator<std::pair<intconst,std::string>>)(in/home/thm/test/test) ==723953==by0x401170:A::deleteMap()(in/home/thm/test/test) ==723953==by0x400F4B:main(in/home/thm/test/test) ==723953== ==723953== ==723953==HEAPSUMMARY: ==723953==inuseatexit:0bytesin0blocks ==723953==totalheapusage:10allocs,10frees,370bytesallocated ==723953== ==723953==Allheapblockswerefreed--noleaksarepossible ==723953== ==723953==Forcountsofdetectedandsuppressederrors,rerunwith:-v ==723953==ERRORSUMMARY:8errorsfrom2contexts(suppressed:6from6)
Why?
此代码可以实现功能要求,但是健壮性并不好,假设在map.erase之后再次使用map当前的iterator,即
voiddeleteMap()
{
for(myMap::iteratorit=map.begin();it!=map.end();++it)
{
map.erase(it->first);
std::cout<<"map.first="<<it->first<<"map.second="<<it->second<<std::endl;
}
}
代码运行就会出现错误,因为it目前指向的对象已经被删掉了。
为了避免程序出现这样的错误,我们应该保证在iterator指向的对象被删掉之前,iterator已经向前移位一。
程序改成如下即可:
voiddeleteMap()
{
for(myMap::iteratorit=map.begin();it!=map.end();)
{
map.erase(it++->first);
}
}
或
voiddeleteMap()
{
for(myMap::iteratorit=map.begin();it!=map.end();)
{
inti=it->first;
++it;
map.erase(i);
}
}
以上所述是小编给大家介绍的for循环中删除map中的元素valgrind检测提示error:Invalidreadofsize8,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!