• 访问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函数既分配空间也进行初始化。

  • 相关阅读:
    JDBC MySQL 实例之 用户管理系统
    利用JDBC连接数据库(MySQL)
    CSS01
    HTML01
    GUI编程02
    GUI编程01
    名词解释
    Navicat MySQL安装
    Eclipse安装Web/JavaEE插件、Eclipse编写HTML代码
    Pascal输出星星
  • 原文地址:https://www.cnblogs.com/cherishui/p/16397828.html
Copyright © 2020-2023  润新知