for循环中删除map中的元素valgrind检测提示error:Invalid read of size 8

废话不多说,先看下面一段代码

#include <iostream>
#include <map>
using namespace std;
class A
{
public:
typedef std::map<int, string> myMap;
void mapInsert(int i, string s)
{
map.insert(std::make_pair(i, s));
}
void deleteMap()
{
for (myMap::iterator it = map.begin(); it != map.end(); ++it)
{
map.erase(it->first);
}
}
private:
myMap map;
};
int main()
{
A a;
a.mapInsert(1, "1");
a.mapInsert(2, "2");
a.mapInsert(3, "3");
a.mapInsert(4, "4");
a.mapInsert(5, "5");
a.deleteMap();
return 0;
}

上述代码编译运行皆没有问题,但是用valgrind检测会提示错误:

valgrind --tool=memcheck --leak-check=full --track-origins=yes ./test # ~/test
==723953== Memcheck, a memory error detector
==723953== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==723953== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==723953== Command: ./test
==723953==
==723953== Invalid read of size 8
==723953== at 0x3431C69E60: std::_Rb_tree_increment(std::_Rb_tree_node_base*) (tree.cc:60)
==723953== by 0x40131C: std::_Rb_tree_iterator<std::pair<int const, std::string> >::operator++() (in /home/thm/test/test)
==723953== by 0x40117C: A::deleteMap() (in /home/thm/test/test)
==723953== by 0x400F4B: main (in /home/thm/test/test)
==723953== Address 0x4c580b8 is 24 bytes inside a block of size 48 free'd
==723953== at 0x4A06016: operator delete(void*) (vg_replace_malloc.c:480)
==723953== by 0x401E23: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (in /home/thm/test/test)
==723953== by 0x401C99: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (in /home/thm/test/test)
==723953== by 0x401AA6: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (in /home/thm/test/test)
==723953== by 0x401729: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::erase(std::_Rb_tree_iterator<std::pair<int const, std::string> >) (in /home/thm/test/test)
==723953== by 0x40134C: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::erase(std::_Rb_tree_iterator<std::pair<int const, std::string> >) (in /home/thm/test/test)
==723953== by 0x401170: A::deleteMap() (in /home/thm/test/test)
==723953== by 0x400F4B: main (in /home/thm/test/test)
==723953==
==723953== Invalid read of size 8
==723953== at 0x3431C69E80: std::_Rb_tree_increment(std::_Rb_tree_node_base*) (tree.cc:68)
==723953== by 0x40131C: std::_Rb_tree_iterator<std::pair<int const, std::string> >::operator++() (in /home/thm/test/test)
==723953== by 0x40117C: A::deleteMap() (in /home/thm/test/test)
==723953== by 0x400F4B: main (in /home/thm/test/test)
==723953== Address 0x4c580a8 is 8 bytes inside a block of size 48 free'd
==723953== at 0x4A06016: operator delete(void*) (vg_replace_malloc.c:480)
==723953== by 0x401E23: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (in /home/thm/test/test)
==723953== by 0x401C99: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (in /home/thm/test/test)
==723953== by 0x401AA6: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (in /home/thm/test/test)
==723953== by 0x401729: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::erase(std::_Rb_tree_iterator<std::pair<int const, std::string> >) (in /home/thm/test/test)
==723953== by 0x40134C: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::erase(std::_Rb_tree_iterator<std::pair<int const, std::string> >) (in /home/thm/test/test)
==723953== by 0x401170: A::deleteMap() (in /home/thm/test/test)
==723953== by 0x400F4B: main (in /home/thm/test/test)
==723953==
==723953==
==723953== HEAP SUMMARY:
==723953== in use at exit: 0 bytes in 0 blocks
==723953== total heap usage: 10 allocs, 10 frees, 370 bytes allocated
==723953==
==723953== All heap blocks were freed -- no leaks are possible
==723953==
==723953== For counts of detected and suppressed errors, rerun with: -v
==723953== ERROR SUMMARY: 8 errors from 2 contexts (suppressed: 6 from 6)

Why?

此代码可以实现功能要求,但是健壮性并不好,假设在map.erase之后再次使用map当前的iterator,即

void deleteMap()
{
for (myMap::iterator it = 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已经向前移位一。

程序改成如下即可:

void deleteMap()
{
for (myMap::iterator it = map.begin(); it != map.end();)
{
map.erase(it++->first);
}
} 

void deleteMap()
{
for (myMap::iterator it = map.begin(); it != map.end();)
{
int i = it->first;
++it;
map.erase(i);
}
}

以上所述是小编给大家介绍的for循环中删除map中的元素valgrind检测提示error:Invalid read of size 8 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • for循环中删除map中的元素valgrind检测提示error:Invalid read of size 8

    废话不多说,先看下面一段代码 #include <iostream> #include <map> using namespace std; class A { public: typedef std::map<int, string> myMap; void mapInsert(int i, string s) { map.insert(std::make_pair(i, s)); } void deleteMap() { for (myMap::iterator i

  • 详解Java删除Map中元素java.util.ConcurrentModificationException”异常解决

    今天在使用map并需要根据某些条件删除map元素时,自然而然想到调用Map中的remove(Object key)函数进行删除,代码如下: //遍历map,如果key<5,那么就删除此元素. Map<Integer, Integer> users = new LinkedHashMap<Integer, Integer>(); for (Map.Entry<Integer,Integer> entry : users.entrySet()){ for (int i

  • Python list列表中删除多个重复元素操作示例

    本文实例讲述了Python list列表中删除多个重复元素操作.分享给大家供大家参考,具体如下: 我们以下面这个list为例,删除其中所有值为6的元素: l=[9,6,5,6,6,7,8,9,6,0] 首先尝试remove方法: l.remove(6) print(l) 结果为:[9, 5, 6, 6, 7, 8, 9, 6, 0],只删除了第一个为6的元素. 如果采用for循环遍历各元素: for x in l: if x == 6: l.remove(x) 结果为[9, 5, 7, 8, 9

  • js中删除数组中的某一元素实例(无下标时)

    1.使用filter数组去重: var arr1 = [1,2,3,4,5,6];//待操作数组 var j = 2;//待删除元素 var noRepeat = function(arr1,arr2){ return arr1.flter(function(e){ return arr2.indexOf(e) == -1; }) }; var arr2 = []; arr2.push(j);//保证待删除数为数组,方便使用过滤器 console.log(noReapeat(arr1,arr2)

  • java中删除 数组中的指定元素方法

    java中删除 数组中的指定元素要如何来实现呢,如果各位对于这个算法不是很清楚可以和小编一起来看一篇关于java中删除 数组中的指定元素的例子. java的api中,并没有提供删除数组中元素的方法.虽然数组是一个对象,不过并没有提供add().remove()或查找元素的方法.这就是为什么类似ArrayList和HashSet受欢迎的原因. 不过,我们要感谢Apache Commons Utils,我们可以使用这个库的ArrayUtils类来轻易的删除数组中的元素.不过有一点需要注意,数组是在大

  • Linux 中删除文本中的回车字符的方法

    当回车字符(Ctrl+M)让你紧张时,别担心.有几种简单的方法消除它们. "回车"字符可以往回追溯很长一段时间 -- 早在打字机上就有一个机械装置或杠杆将承载纸滚筒的机架移到右边,以便可以重新在左侧输入字母.他们在 Windows 上的文本文件上保留了它,但从未在 Linux 系统上使用过.当你尝试在 Linux 上处理在 Windows 上创建的文件时,这种不兼容性有时会导致问题,但这是一个非常容易解决的问题. 如果你使用 od(八进制转储octal dump)命令查看文件,那么回车

  • java中删除数组中重复元素方法探讨

    问题:比如我有一个数组(元素个数为0哈),希望添加进去元素不能重复. 拿到这样一个问题,我可能会快速的写下代码,这里数组用ArrayList. 复制代码 代码如下: private static void testListSet(){        List<String> arrays = new ArrayList<String>(){            @Override            public boolean add(String e) {         

  • php中删除字符串中最先出现某个字符的实现代码

    复制代码 代码如下: $a = "字符串";$c= explode("要删除的文字", $a, 2); $b = $c[0].$c[1]; explode (PHP 3, PHP 4, PHP 5) explode -- 使用一个字符串分割另一个字符串 描述 array explode ( string separator, string string [, int limit] ) 此函数返回由字符串组成的数组,每个元素都是 string 的一个子串,它们被字符串

  • shell中删除文件中重复行的方法

    Linux下文本处理工具很丰富很强大,例如这样一个文件: 复制代码 代码如下: cat log www.jb51.net 192.168.1.1www.jb51.net 192.168.1.1www.jb51.net 192.168.1.2ffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeefffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeggggggggggggggg

  • VB.NET 中删除DataGridView中所选行的小例子

    复制代码 代码如下: For Each r As DataGridViewRow In DataGridView1.SelectedRows    If Not r.IsNewRow Then        DataGridView1.Rows.Remove(r)    End IfNext 其实就是一个IsNewRow属性,判断是不是为新选中的行,如果不是,remove!

随机推荐