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

 1 #include <iostream>
 2 #include <map>
 3
 4 using namespace std;
 5
 6 class A
 7 {
 8     public:
 9     typedef std::map<int, string> myMap;
10
11     void mapInsert(int i, string s)
12     {
13         map.insert(std::make_pair(i, s));
14     }
15
16     void deleteMap()
17     {
18         for (myMap::iterator it = map.begin(); it != map.end(); ++it)
19         {
20             map.erase(it->first);
21         }
22     }
23     private:
24     myMap map;
25 };
26
27 int main()
28 {
29     A a;
30     a.mapInsert(1, "1");
31     a.mapInsert(2, "2");
32     a.mapInsert(3, "3");
33     a.mapInsert(4, "4");
34     a.mapInsert(5, "5");
35
36     a.deleteMap();
37
38     return 0;
39 }

上述代码编译运行皆没有问题,但是用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);
        }
    }
时间: 2024-10-20 02:38:44

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

【方法1】删除Map中Value反复的记录,而且仅仅保留Key最小的那条记录

介绍 晚上无聊的时候,我做了一个測试题,測试题的大体意思是:删除Map中Value反复的记录,而且仅仅保留Key最小的那条记录. 比如: I have a map with duplicate values: ("A", "1"); ("B", "2"); ("C", "2"); ("D", "3"); ("E", "

【方法2】删除Map中Value重复的记录,并且只保留Key最小的那条记录

根据guigui111111的建议:先把Map按Key从大到小排序,然后再把Key和Value互换.这也是一种很好的思路,我写了一下代码,顺便贴上来,供大家参考与分享. package shuai.study.map; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import j

删除Map中Value重复的记录,并且只保留Key最小的那条记录

介绍 晚上无聊的时候,我做了一个测试题,测试题的大体意思是:删除Map中Value重复的记录,并且只保留Key最小的那条记录. 例如: I have a map with duplicate values: ("A", "1"); ("B", "2"); ("C", "2"); ("D", "3"); ("E", "3

【方法3:Perl版本】删除Map中Value重复的记录,并且只保留Key最小的那条记录

icemouse210写了一个Perl版本的,发挥了脚本高度封装的优势.我把代码贴出来,供大家参考分享. #!/user/bin/perl -w use English; use strict; use warnings; my %test_hash=( "A" => '1', "B" => '2', "C" => "2", "D" => "3", "E

关于java中ArrayList的快速失败机制的漏洞——使用迭代器循环时删除倒数第二个元素不会报错

一.问题描述 话不多说,先上代码: public static void main(String[] args) throws InterruptedException { List<String> list = new ArrayList<String>(); list.add("第零个"); list.add("第一个"); list.add("第二个"); list.add("第三个"); lis

遍历map和删除map中的一个entry

一.最常见的,需要key和value都需要时 public static void main(String[] args) { Map<Integer,Integer> map = new HashMap<Integer,Integer>(); map.put(33, 333); map.put(22, 222); map.put(11, 111); for(Map.Entry<Integer, Integer> entry:map.entrySet()){ Syste

JS中删除数组中元素的几种方法

1.删除数组中的最后一个元素: 1 <script> 2 // 首先定义一个数组 3 var arr = [1,2,3,4,5]; 4 // 输出数组 5 console.log(arr);//结果为[1,2,3,4,5] 6 // 调用pop 方法 7 arr.pop(); 8 // 再次输出 9 console.log(arr);//结果为[1,2,3,4] 10 </script> 使用pop()方法只能删除数组中的最后一个元素. 2.删除数组中的第一个元素: 1 <s

Java中删除List中相同元素的两种方法

Java中两种删除List中相同element的方法,一种维护List原先的元素顺序,另一种不维护List原先的元素顺序. package stage3; import java.util.Iterator; public class RemoveTheElement { public static <E> void removeDuplicateWithoutOrder(java.util.List<E> list) { java.util.Set<E> set = 

JS中删除数组中的元素方法

删除指定下标数组元素 Array.prototype.del=function(index){ if(isNaN(index)||index>=this.length){ return false; } for(var i=0,n=0;i<this.length;i++){ if(this[i]!=this[index]){ this[n++]=this[i]; } } this.length-=1; }; 删除指定元素 Array.prototype.indexOf = function(v