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(, "");
a.mapInsert(, "");
a.mapInsert(, "");
a.mapInsert(, "");
a.mapInsert(, ""); a.deleteMap(); return ;
}
上述代码编译运行皆没有问题,但是用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的更多相关文章
- js删除map中元素
js中删除map中元素后,map的长度不变,这时需要我们自己处理 delete vacc[0]; delete vacc[1]; ClearNullArr(vacc); //清除vacc中的null值 ...
- 【方法1】删除Map中Value反复的记录,而且仅仅保留Key最小的那条记录
介绍 晚上无聊的时候,我做了一个測试题,測试题的大体意思是:删除Map中Value反复的记录,而且仅仅保留Key最小的那条记录. 比如: I have a map with duplicate val ...
- detach([expr]) 从DOM中删除所有匹配的元素。
detach([expr]) 概述 从DOM中删除所有匹配的元素.大理石构件 这个方法不会把匹配的元素从jQuery对象中删除,因而可以在将来再使用这些匹配的元素.与remove()不同的是,所有绑定 ...
- 可以用for循环直接删除ArrayList的特定元素吗?可能会出现什么问题?怎样解决?
for循环直接删除ArrayList中的特定元素是错的,不同的for循环会发生不同的错误,泛型for会抛出 ConcurrentModificationException,普通的for想要删除集合中重 ...
- Java根据条件删除Map中元素
今天在写程序过程中,需要根据判断条件删除一个Map中的相应数据,我自然而然想到可以通过调用Map中的remove(Object key)函数进行删除:代码如下: public Map<Doubl ...
- 关于java中ArrayList的快速失败机制的漏洞——使用迭代器循环时删除倒数第二个元素不会报错
一.问题描述 话不多说,先上代码: public static void main(String[] args) throws InterruptedException { List<Strin ...
- C#实现在foreach遍历中删除集合中的元素(方法总结)
目录 方法一:采用for循环,并且从尾到头遍历 方法二:使用递归 方法三:通过泛型类实现IEnumerator 在foreach中删除元素时,每一次删除都会导致集合的大小和元素索引值发生变化,从而导致 ...
- vector中删除第k个元素的巧妙方法
假设我们定义了一个vector如下: vector<int> v;v.push_back(1);...v.push_back(255); 如果要删除第k个元素的话,应该这样写: (1)如果 ...
- JS中删除数组中的元素方法
删除指定下标数组元素 Array.prototype.del=function(index){ if(isNaN(index)||index>=this.length){ return fals ...
随机推荐
- .net之GridView、DataList、DetailsView(二)
GridView自带分页功能,效率不高,适用于小数据量的显示. protected void GridView1_PageIndexChanging(object sender, GridViewPa ...
- PHP资源,库,工具大全
内容包括:库.框架.模板.安全.代码分析.日志.第三方库.配置工具.Web 工具.书籍.电子书.经典博文等等. 大家可以搜索其它语言,如awesome-java的https://github.com/ ...
- Gradle 构建工具
参考文章: 作者:ghui 链接:https://www.zhihu.com/question/30432152/answer/48239946 来源:知乎 著作权归作者所有.商业转载请联系作者获得授 ...
- WEBserver、应用程序server、HTTPserver差别
WEBserver.应用程序server.HTTPserver差别 WEBserver.应用程序server.HTTPserver有何差别?IIS.Apache.Tomcat.Weblogic.Web ...
- ubuntu 解决更换源失败问题
用图形界面命令打开窗口在终端输入 gksudo nautilus打开一个图形窗口 (注意在这个图形窗口下 任何目录下的文件都是可以删除的) /ect/apt删除下面的sources.list和备份文件 ...
- 基于react-native android的新闻app的开发
使用平台:android 代码获取地址:https://github.com/wuwanyu/ReactNative-Android-MovieDemo 项目展示: 结构图: SpalashScree ...
- Unity3d 摇杆奖励
单个单元: publicclass RockerSingle : MonoBehaviour { // 枚举.类别 RockerType rockerType; //是否有效,最上面的为无效,即为f ...
- 一个关于运维人员做事的很好的case,拿出来和大家共勉
很久没有写KM了,最近lester这边在梳理CDB这边存在的问题,并推动那些问题解决措施的落地.无疑当前CDB存在比较多的问题,也有很多坑.需要我们运维和开发的同学多思考问题的根源和解决办法,并付诸实 ...
- 2.二级接口ListableBeanFactory
这个随笔主要讲的是ListableBeanFactory package org.springframework.beans.factory; import java.lang.annotation. ...
- 优化tomcat启动速度
1.去掉不需要的jar包,这样tomcat在启动时就可以少加载jar包里面的class文件. 2.跳过一些与TLD files.注解.网络碎片无关的jar包,通过在conf/catalina.prop ...