zoukankan      html  css  js  c++  java
  • 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);
            }
        }
  • 相关阅读:
    jsp 特殊标签
    poj 1753 Flip Game 高斯消元 异或方程组 求最值
    zoj 3155 Street Lamp 高斯消元 异或方程组 求方案数
    poj1222 EXTENDED LIGHTS OUT 高斯消元解异或方程组 模板
    zoj 3930 Dice Notation 模拟
    zoj 3157 Weapon 线段树求逆序对数
    hdu 1242 Rescue BFS+优先队列
    hdu 3466 Proud Merchants 贪心+01背包
    zoj 3689 Digging 贪心+01背包
    hdu 2602 Bone Collector 01背包模板
  • 原文地址:https://www.cnblogs.com/tanghuimin0713/p/5651639.html
Copyright © 2011-2022 走看看