C++ vector iterators incompatible问题,erase()用法

林泉926 2015-03-12 07:44:00
如图所示,需要删除vector的一个元素,出现Debug assertion failed错误,描述为:vector iterators incompatible,不知道哪个地方出了问题,而且我在循环语句上面测试输出*itr时也提示vector iterator not deferencablede 错误,对vector这块实践很少,erase()也是第一次用,实在找不到原因了,求大神指点一下!不胜感激!
else
{
vector<int>::iterator itr = chQueue->RelatedEvtID.begin();
while(itr != chQueue->RelatedEvtID.end())
{
if((*itr )== relatedEvtID)
{
itr =chQueue->RelatedEvtID.erase(itr);
}
else
++itr;

}
...全文
655 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
Cql_liliang 2015-03-16
  • 打赏
  • 举报
回复
vector容器你删除或者更改元素会导致迭代器(iterator)失效,从而导致错误。 functor写成自己想要的 你可以这样:vector<XX>::iterator = pos = remove_if(vec.begin() , vec.end() , functor) ; vec.erase(pos , vec.end()) ;
林泉926 2015-03-16
  • 打赏
  • 举报
回复
引用 23 楼 sniffer12345 的回复:
[quote=引用 22 楼 u011744838 的回复:] [quote=引用 20 楼 sniffer12345 的回复:] [quote=引用 13 楼 u011744838 的回复:] [quote=引用 11 楼 Falleyes 的回复:] 第一次利用C++写这么大的程序,确实有很多需要学习的地方,多谢指教!请问你说的锁方面是什么意思?现在主要是被vector这块卡住了,不知道怎么解决,不知道您有什么好的建议?谢谢!
你们项目经理是怎么想的呢。。C++本身就是很复杂的工具,又是做网络的不是做做UI,要是不熟悉的话会很难掌握的, 建议要不就换成JAVA或者python你们熟悉的,要不就使用别人写好的框架。有很多这种写好的服务器引擎啊。如果是准备公司自己弄一套,也得组建一个熟练团队来做这事,要不真心很难弄 你提的vector的问题上边别人已经说得很清楚啦, “vector<int>是不能用memset初始化的” 因为vector是stl的,是c++中的类,类在初始化的时候有可能会设置一些成员变量,而你memset是直接对这块内存清空,那么很容易就会破坏掉它的结构的。 解决的方法,要么针对你的结构体写初始化,不要直接memset。 但是你写的是packet,按理是要序列化的吧?一般用vector是变长的,除非你清楚的知道自己是要做什么,并且在序列化反序列化的时候做相应的操作,否则最好是用定长数组。要不过段时间你就会遇到另一个坑啦 我建议你还是用用别人的框架吧,比如raknet,比如libevent。协议的话用protocal buffer之类的 [/quote] 嗯,明白了,谢谢您!我还是一名学生,想借着写这个程序好好学习C++,还有很多不足,见谅!
林泉926 2015-03-16
  • 打赏
  • 举报
回复
引用 25 楼 Falleyes 的回复:
[quote=引用 24 楼 Falleyes 的回复:] 嗯嗯,如楼上所说,不要使用memset。 你要memset的这个类的成员可以依次重新赋值,不要直接memset内存空间。或者简单点,直接调用构造函数,重新构造一个新对象~ 关于对象,你看看面向对象的概念吧,因为这是C++和C最大的不用之处。
不同之处。。。。[/quote] 嗯 明白了,谢谢您的耐心解答!
林泉926 2015-03-15
  • 打赏
  • 举报
回复
引用 20 楼 sniffer12345 的回复:
[quote=引用 13 楼 u011744838 的回复:] [quote=引用 11 楼 Falleyes 的回复:] [quote=引用 4 楼 u011744838 的回复:] [quote=引用 1 楼 Falleyes 的回复:] 你的chQueue->RelatedEvtID是个什么类型的vector?是否匹配vector<int>? 或者你直接
//vector<int>::iterator itr = chQueue->RelatedEvtID.begin();
auto itr=chQueue->RelatedEvtID.begin();
都是vector<int>类型,用auto还是会出现vector iterators incompatible的错误提示,还有别的办法吗?[/quote]楼主发完整代码吧,这样看也不好分析问题。chQueue的定义[/quote]
Packet* 
	phy::PHYPacketGet(int relatedEvtID, int srcnodeindex)
{
	Packet *PkReceived;
	bool lastDest = false;
	//每个数据包根据其相应的目的地址都有一个RelatedEvtID,只要判断RelatedEvtID相等,
	//则可判断是否为要接收的数据包。
	//做法为:遍历发送缓冲区内的每一个数据包,判断RelatedEvtID是否和要找的事件ID号相等
	//如果相等,则是要接收的数据包,否则,不是。
	for(int i = 0;i<PacketSendingBufferSize;++i)
	{
		int tmp = 0;
		Packet *pkQueue = PacketSendingBuffer.LookUpPacket(i);
		hdr_cmn *chQueue = HDR_CMN(pkQueue);//访问hdr_cmn头
		hdr_phy *phQueue = HDR_PHY(pkQueue);//访问hdr_phy头
		for(vector<int>::size_type j = 0; j != chQueue->RelatedEvtID.size(); ++j)
		{
			if(chQueue->RelatedEvtID[j] == relatedEvtID)
			{
				PkReceived = pkQueue;
				//20150127 待修改,判断这是不是最后一次对该数据包的接收,
				//即当前地址是不是数据包的最后一个目的地址
				if(chQueue->RelatedEvtID.size() <= 1)
				{
					pkQueue = new Packet;
					lastDest = true;
				}
				else
				{
					cout<<chQueue->RelatedEvtID[0]<<endl;
					vector<int>::iterator itr = chQueue->RelatedEvtID.begin();
					//auto itr = chQueue->RelatedEvtID.begin();
					cout<<*itr<<endl;
					while(itr != chQueue->RelatedEvtID.end())
					{
						if((*itr )== relatedEvtID)
							{
								itr =chQueue->RelatedEvtID.erase(itr);
								break;
						}
						else
							++itr;
						
					}
					
				}
				tmp = 1;
				break;
			}
			else
			{
				cout<<"Not Find the packet to be received!"<<endl;
				SimBreakTag = 1;
			}

		}
		if(tmp == 1)
			break;
	}
}
	
这是当前函数下对RelatedEvtID的操作。 [/quote] 代码好可怕。。就这样erase,就这样new。。 看样子还是网络收发的地方,也不知道锁方面怎么弄的。。[/quote] 第一次利用C++写这么大的程序,确实有很多需要学习的地方,多谢指教!请问你说的锁方面是什么意思?现在主要是被vector这块卡住了,不知道怎么解决,不知道您有什么好的建议?谢谢!
林泉926 2015-03-15
  • 打赏
  • 举报
回复
引用 19 楼 Falleyes 的回复:
[quote=引用 17 楼 u011744838 的回复:] 会不会因为使用了memset的原因,但是memset是初始化的Packet空间,hdr_cmn并不是Packet的成员变量啊,只是在初始化空间后对它进行访问而已。请指教,太感谢您了。
使用了memset初始化空间。。。你的chQueue在这段空间里吗?vector<int>是不能用memset初始化的。如果这样做了,会出现异常Debug assertion failed,和你的情况貌似一样。[/quote] 我是先初始化的Packet空间,然后用chQueue去访问这段空间
return (hdr_cmn*) p->access(offset_);
,这也是不可以的吗?那如果我即需要初始化一段新空间,又需要对vector进行操作,应该怎么办呢?
Falleyes 2015-03-15
  • 打赏
  • 举报
回复
引用 24 楼 Falleyes 的回复:
嗯嗯,如楼上所说,不要使用memset。 你要memset的这个类的成员可以依次重新赋值,不要直接memset内存空间。或者简单点,直接调用构造函数,重新构造一个新对象~ 关于对象,你看看面向对象的概念吧,因为这是C++和C最大的不用之处。
不同之处。。。。
Falleyes 2015-03-15
  • 打赏
  • 举报
回复
嗯嗯,如楼上所说,不要使用memset。 你要memset的这个类的成员可以依次重新赋值,不要直接memset内存空间。或者简单点,直接调用构造函数,重新构造一个新对象~ 关于对象,你看看面向对象的概念吧,因为这是C++和C最大的不用之处。
sniffer12345 2015-03-15
  • 打赏
  • 举报
回复
引用 22 楼 u011744838 的回复:
[quote=引用 20 楼 sniffer12345 的回复:] [quote=引用 13 楼 u011744838 的回复:] [quote=引用 11 楼 Falleyes 的回复:] 第一次利用C++写这么大的程序,确实有很多需要学习的地方,多谢指教!请问你说的锁方面是什么意思?现在主要是被vector这块卡住了,不知道怎么解决,不知道您有什么好的建议?谢谢!
你们项目经理是怎么想的呢。。C++本身就是很复杂的工具,又是做网络的不是做做UI,要是不熟悉的话会很难掌握的, 建议要不就换成JAVA或者python你们熟悉的,要不就使用别人写好的框架。有很多这种写好的服务器引擎啊。如果是准备公司自己弄一套,也得组建一个熟练团队来做这事,要不真心很难弄 你提的vector的问题上边别人已经说得很清楚啦, “vector<int>是不能用memset初始化的” 因为vector是stl的,是c++中的类,类在初始化的时候有可能会设置一些成员变量,而你memset是直接对这块内存清空,那么很容易就会破坏掉它的结构的。 解决的方法,要么针对你的结构体写初始化,不要直接memset。 但是你写的是packet,按理是要序列化的吧?一般用vector是变长的,除非你清楚的知道自己是要做什么,并且在序列化反序列化的时候做相应的操作,否则最好是用定长数组。要不过段时间你就会遇到另一个坑啦 我建议你还是用用别人的框架吧,比如raknet,比如libevent。协议的话用protocal buffer之类的
林泉926 2015-03-14
  • 打赏
  • 举报
回复
引用 16 楼 Falleyes 的回复:
[quote=引用 15 楼 u011744838 的回复:] [quote=引用 14 楼 Falleyes 的回复:] 喔。。。好多东西。你调试看看,断点到迭代器赋值的地方,chQueue指向的内容是什么,这个指针是不是个野指针?
是有值的,解引用的时候
const _Container_base12 *_Getcont() const
		{	// get owning container
		return (_Myproxy == 0 ? 0 : _Myproxy->_Mycont);
		}
其中就显示_Myproxy 等于0了,不知道为啥[/quote]有可能是_Myproxy这个值是个新对象的成员,从来没有修改过,编译器把这个值默认初始化为int型的默认值0了。 你的错误是Debug assertion failed,所以应该是对象的问题。你对vector的操作是没有问题的,我用普通vector<int>数组测试是通过的,无论是vs还是g++。检查你的对象吧![/quote] 不好意思,我没太明白检查对象的意思?我该从哪开始检查呢?忽然想起来,我首先定义了一个Packet类,生成一个新的Packet对象时采用的是这种方法
p = new Packet; 
		p->bits_ = new unsigned char[hdrlen_];//hdrlen代表数据包包头的大小
		if (p == 0 || p->bits_ == 0)
			abort();
	
	bzero(p->bits_, hdrlen_) // 初始化这段内存空间,相当于这段内存里并没有任何数据
其中#define bzero(dest,count)     memset(dest,0,count)//用0来初始化以dest地址开头的连续count个的地址空间
然后我通过这种方式
 hdr_cmn *chQueue = HDR_CMN(pkQueue);//访问hdr_cmn头
用结构体hdr_cmn访问Packet的空间,进而对hdr_cmn指针chQueue中的vector变量RelatedEvtID进行操作。 会不会因为使用了memset的原因,但是memset是初始化的Packet空间,hdr_cmn并不是Packet的成员变量啊,只是在初始化空间后对它进行访问而已。请指教,太感谢您了。
Falleyes 2015-03-14
  • 打赏
  • 举报
回复
引用 15 楼 u011744838 的回复:
[quote=引用 14 楼 Falleyes 的回复:] 喔。。。好多东西。你调试看看,断点到迭代器赋值的地方,chQueue指向的内容是什么,这个指针是不是个野指针?
是有值的,解引用的时候
const _Container_base12 *_Getcont() const
		{	// get owning container
		return (_Myproxy == 0 ? 0 : _Myproxy->_Mycont);
		}
其中就显示_Myproxy 等于0了,不知道为啥[/quote]有可能是_Myproxy这个值是个新对象的成员,从来没有修改过,编译器把这个值默认初始化为int型的默认值0了。 你的错误是Debug assertion failed,所以应该是对象的问题。你对vector的操作是没有问题的,我用普通vector<int>数组测试是通过的,无论是vs还是g++。检查你的对象吧!
林泉926 2015-03-14
  • 打赏
  • 举报
回复
引用 14 楼 Falleyes 的回复:
喔。。。好多东西。你调试看看,断点到迭代器赋值的地方,chQueue指向的内容是什么,这个指针是不是个野指针?
是有值的,解引用的时候
const _Container_base12 *_Getcont() const
		{	// get owning container
		return (_Myproxy == 0 ? 0 : _Myproxy->_Mycont);
		}
其中就显示_Myproxy 等于0了,不知道为啥
sniffer12345 2015-03-14
  • 打赏
  • 举报
回复
引用 13 楼 u011744838 的回复:
[quote=引用 11 楼 Falleyes 的回复:] [quote=引用 4 楼 u011744838 的回复:] [quote=引用 1 楼 Falleyes 的回复:] 你的chQueue->RelatedEvtID是个什么类型的vector?是否匹配vector<int>? 或者你直接
//vector<int>::iterator itr = chQueue->RelatedEvtID.begin();
auto itr=chQueue->RelatedEvtID.begin();
都是vector<int>类型,用auto还是会出现vector iterators incompatible的错误提示,还有别的办法吗?[/quote]楼主发完整代码吧,这样看也不好分析问题。chQueue的定义[/quote]
Packet* 
	phy::PHYPacketGet(int relatedEvtID, int srcnodeindex)
{
	Packet *PkReceived;
	bool lastDest = false;
	//每个数据包根据其相应的目的地址都有一个RelatedEvtID,只要判断RelatedEvtID相等,
	//则可判断是否为要接收的数据包。
	//做法为:遍历发送缓冲区内的每一个数据包,判断RelatedEvtID是否和要找的事件ID号相等
	//如果相等,则是要接收的数据包,否则,不是。
	for(int i = 0;i<PacketSendingBufferSize;++i)
	{
		int tmp = 0;
		Packet *pkQueue = PacketSendingBuffer.LookUpPacket(i);
		hdr_cmn *chQueue = HDR_CMN(pkQueue);//访问hdr_cmn头
		hdr_phy *phQueue = HDR_PHY(pkQueue);//访问hdr_phy头
		for(vector<int>::size_type j = 0; j != chQueue->RelatedEvtID.size(); ++j)
		{
			if(chQueue->RelatedEvtID[j] == relatedEvtID)
			{
				PkReceived = pkQueue;
				//20150127 待修改,判断这是不是最后一次对该数据包的接收,
				//即当前地址是不是数据包的最后一个目的地址
				if(chQueue->RelatedEvtID.size() <= 1)
				{
					pkQueue = new Packet;
					lastDest = true;
				}
				else
				{
					cout<<chQueue->RelatedEvtID[0]<<endl;
					vector<int>::iterator itr = chQueue->RelatedEvtID.begin();
					//auto itr = chQueue->RelatedEvtID.begin();
					cout<<*itr<<endl;
					while(itr != chQueue->RelatedEvtID.end())
					{
						if((*itr )== relatedEvtID)
							{
								itr =chQueue->RelatedEvtID.erase(itr);
								break;
						}
						else
							++itr;
						
					}
					
				}
				tmp = 1;
				break;
			}
			else
			{
				cout<<"Not Find the packet to be received!"<<endl;
				SimBreakTag = 1;
			}

		}
		if(tmp == 1)
			break;
	}
}
	
这是当前函数下对RelatedEvtID的操作。 [/quote] 代码好可怕。。就这样erase,就这样new。。 看样子还是网络收发的地方,也不知道锁方面怎么弄的。。
Falleyes 2015-03-14
  • 打赏
  • 举报
回复
引用 17 楼 u011744838 的回复:
会不会因为使用了memset的原因,但是memset是初始化的Packet空间,hdr_cmn并不是Packet的成员变量啊,只是在初始化空间后对它进行访问而已。请指教,太感谢您了。
使用了memset初始化空间。。。你的chQueue在这段空间里吗?vector<int>是不能用memset初始化的。如果这样做了,会出现异常Debug assertion failed,和你的情况貌似一样。
Falleyes 2015-03-14
  • 打赏
  • 举报
回复
调试会吗? 比如Visual Studio,把断点设置到vector<int>::iterator itr = chQueue->RelatedEvtID.begin();这一句。 然后开始调试,执行到这一句自动中断,然后看局部变量chQueue的数据,指向了什么,指向的数据是多少。
Falleyes 2015-03-13
  • 打赏
  • 举报
回复
喔。。。好多东西。你调试看看,断点到迭代器赋值的地方,chQueue指向的内容是什么,这个指针是不是个野指针?
Falleyes 2015-03-13
  • 打赏
  • 举报
回复
引用 4 楼 u011744838 的回复:
[quote=引用 1 楼 Falleyes 的回复:] 你的chQueue->RelatedEvtID是个什么类型的vector?是否匹配vector<int>? 或者你直接
//vector<int>::iterator itr = chQueue->RelatedEvtID.begin();
auto itr=chQueue->RelatedEvtID.begin();
都是vector<int>类型,用auto还是会出现vector iterators incompatible的错误提示,还有别的办法吗?[/quote]楼主发完整代码吧,这样看也不好分析问题。chQueue的定义
此后三年 2015-03-13
  • 打赏
  • 举报
回复
引用 8 楼 u011744838 的回复:
[quote=引用 7 楼 a30037338 的回复:] RelatedEvtID是一个vector? 迭代器解引用得到的是一个int型的值, 你拿它和RelatedEvtID(一个vector对象) 比较。。。
比较的值也是一个int型,是relatedEvtID,您看错了。但是我定义
vector<int>::iterator itr = chQueue->RelatedEvtID.begin();
       cout<<*itr<<endl;
这样也有错误,提示vector iterator not deferencablede ,不知道怎么回事了就。[/quote] 失误失误, 问题出在erase函数上, 调用了erase函数之后, 迭代器同时也被擦除了, 迭代器必须重新赋值才能使用。
赵4老师 2015-03-13
  • 打赏
  • 举报
回复
VS IDE中,在不明白的符号上点鼠标右键,选转到定义。
林泉926 2015-03-13
  • 打赏
  • 举报
回复
引用 7 楼 a30037338 的回复:
RelatedEvtID是一个vector? 迭代器解引用得到的是一个int型的值, 你拿它和RelatedEvtID(一个vector对象) 比较。。。
比较的值也是一个int型,是relatedEvtID,您看错了。但是我定义
vector<int>::iterator itr = chQueue->RelatedEvtID.begin();
       cout<<*itr<<endl;
这样也有错误,提示vector iterator not deferencablede ,不知道怎么回事了就。
此后三年 2015-03-13
  • 打赏
  • 举报
回复
RelatedEvtID是一个vector? 迭代器解引用得到的是一个int型的值, 你拿它和RelatedEvtID(一个vector对象) 比较。。。
加载更多回复(8)

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧