"vector iterators incompatible"及一些感想

        首先要感谢下这个前辈:http://www.2cto.com/kf/201110/108902.html,是他的帖子给了我方向。

        先上一段代码:

#include 
#include 

class Base
{
public:
	std::vector vec;
	int a;
};

int main()
{
	Base base;
	memset(&base, 0, sizeof(base));
	base.vec.push_back(1);
	base.vec.push_back(2);
	base.vec.push_back(3);
	base.vec.push_back(4);

	std::vector::iterator iter;
	for( iter = base.vec.begin(); iter != base.vec.end(); ++iter )
	{
		*iter = 10;
		std::cout<<*iter<


       不知道你能不能看出来这段代码是否有问题,有什么问题?

       好吧,这就是今天要提的运行时崩溃错误“vector iterator incompatible”。

       这个问题是一个朋友在弄他自己的服务器程序时遇见的,然后让我帮他解决。上面的代码是我将他的问题换了种比较简洁的方式来呈现。编译上述程序没有任何问题,但是

运行时总会在for( iter = base.vec.begin(); iter != base.vec.end(); ++iter ) 时崩掉。崩溃界面如下:

       

        当时很疑惑,怎么会迭代器不匹配呢。明明就是同一个类型,用begin()赋值的时候也没错啊,调试看iter的数据也是正确的。然后就百度、google了一下。发现了文章最开

始的帖子,然后对照了他说的一些东西。

        首先是类型不匹配,例如用int型的向量迭代器与char型的向量迭代器进行比对操作,其他编译器我不知道,我用的是VS2010,如果迭代器不匹配,编译根本通不过;

        其次,如果是容器结构发生变化,比如erase某个iter之类的,报错也不是这个,而是“vecotr iterator not dereferencable”。意思是迭代器不可引用,已经失效。

        既然上面两种都不是引发我们问题的原因,那么是什么导致的呢。在上面帖子最后,他还提到了跟踪到底层库是发现某个变量值为0,于是我也调试代码,跟踪到vector的

源码中,步骤如下:

1.进入vector函数 operator != :

	bool operator!=(const _Myiter& _Right) const
		{	// test for iterator inequality
		return (!(*this == _Right));
		}


2.进入重载的 operator == :

	bool operator==(const _Myiter& _Right) const
		{	// test for iterator equality
		_Compat(_Right);
		return (this->_Ptr == _Right._Ptr);
		}


3.进入_Compa函数:

 #if _ITERATOR_DEBUG_LEVEL == 2
	void _Compat(const _Myiter& _Right) const
		{	// test for compatible iterator pair
		if (this->_Getcont() == 0
			|| this->_Getcont() != _Right._Getcont())
			{	// report error
			_DEBUG_ERROR("vector iterators incompatible");
			_SCL_SECURE_INVALID_ARGUMENT;
			}
		}

 #elif
...
#endif


4._Getcont函数:

	const _Container_base12 *_Getcont() const
		{	// get owning container
		return (_Myproxy == 0 ? 0 : _Myproxy->_Mycont);
		}

        发现果然“_Myproxy”指针的值是0。然后我就查看朋友的代码,发现他程序中确实有个地方使用了memset,而且传入的指针是一个野指针,导致了vector内部某些值被错误修改。

       至此,问题解决。不过,我还是想粗浅的展示一些vector的细节,更详细的待以后再说吧。

       打印上面代码中base的两个成员变量vec和a的地址,分别是0x0044F8FC,0X0044F910,这意味着vector一出来至少就占用了20个字节。在vector类中有如下定义:

pointer _Myfirst;	// pointer to beginning of array
	pointer _Mylast;	// pointer to current end of sequence
	pointer _Myend;	// pointer to end of array
	_Alty _Alval;	// allocator object for values
 

       同时std::vector<_Ty,_Alloc>通过基类_Vector_val<_Ty,_Alloc>包含了一个_Container_proxy对象,_Container_proxy::_Myfirstiter指向了一个单向链表P的头指针,P中包含

一个vector对象的所有迭代器的指针。

       当我们使用memset初始化Base类时,其实也把所有的这些指针都置0了。所以,使用memset的时候还是需要很慎重,至少有stl容器的时候最好不要用这种方式去初始化

一块内存。

        关于“vector iteraotr incompatible”就暂时讲到这吧,近期打算以侯捷老师的《STL源码剖析》为参考,通读下STL的源码,了解下容器内部构造以及设计理念。这对于以

后自己编写游戏引擎内存管理什么的或许有所帮助吧。      

你可能感兴趣的:(STL,常见错误)