访问Vector崩溃问题分析

近期工作中遇到在访问vector越界问题,本文小结此问题。

问题描述

通过某种操作,触发vector访问越界,在debug环境上崩溃,而release环境上没有崩溃。

问题分析

在往vector中添加元素时,会分配大于实际元素个数的空间。具体分配策略关键源码如下:


size_type _Grow_to(size_type _Count) const
		{	// grow by 50% or at least to _Count
		size_type _Capacity = capacity();

		_Capacity = max_size() - _Capacity / 2 < _Capacity
			? 0 : _Capacity + _Capacity / 2;	// try to grow by 50%
		if (_Capacity < _Count)
			_Capacity = _Count;
		return (_Capacity);
		}

max_size()vector中预定于的最大容量,当容量(_Capacity)不够时,以 (_Capacity + _Capacity/2) 作为新容量进行扩容,也就是按照当前容量的50%来增长。

[]取值函数如下:


	const_reference operator[](size_type _Pos) const
		{	// subscript nonmutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 2
		if (size() <= _Pos)
			{	// report error
			_DEBUG_ERROR("vector subscript out of range");
			_SCL_SECURE_OUT_OF_RANGE;
			}

 #elif _ITERATOR_DEBUG_LEVEL == 1
		_SCL_SECURE_VALIDATE_RANGE(_Pos < size());
 #endif /* _ITERATOR_DEBUG_LEVEL */

		return (*(this->_Myfirst() + _Pos));
		}

由此可见,在Debug版本下,使用[]方式取值,会触发异常,Release版本不会。

at取值函数如下:


	const_reference at(size_type _Pos) const
		{	// subscript nonmutable sequence with checking
		if (size() <= _Pos)
			_Xout_of_range("invalid vector<T> subscript");
		return (*(this->_Myfirst() + _Pos));
		}


使用at函数,不管Debug还是Release,都会判断下标有效性,越界则报异常。

小结

综上所述,对于vector中已分配但尚未使用的空间,使用[]方式,在Debug上会触发异常,Release不会。虽说Release不触发异常,但后续读写到的是未定义数值,行为不确定,要坚决避免。

at方式读写,下标只能是真实数据下标范围,不能越界。

另外一个知识点:vector的reserve函数只分配空间,resize函数既分配空间也进行初始化。

posted @ 2022-06-21 18:06  浩天之家  阅读(876)  评论(0编辑  收藏  举报