for循环中删除map中的元素valgrind检测提示error:Invalid read of size 8
2019/7/10 22:56:47
本文主要是介绍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 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对找一找教程网网站的支持!
这篇关于for循环中删除map中的元素valgrind检测提示error:Invalid read of size 8的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享