DEBUG下,VS 2010的vector和相關迭代器的安全檢查和記錄功能

 

本文分析DEBUG配置下,VS 2010中std::vector和相關迭代器提供的安全檢查和記錄功能。有的功能非常耗時。幸好在RELEASE配置下,這些功能都被預編譯指令去掉了。當然這也說明,針對VC程序的效率測試必須採用RELEASE版本,否則測試結果很難說明問題。

 

std::vector和std::vector迭代器的類圖



其中,_Vector_iterator<_Myvec>是std::vector<_Ty,_Alloc>::begin()返回的類型,

_Vector_const_iterator<_Myvec>是相應的const iterator

迭代器的有效性檢查

在DEBUG配置下,_Vector_const_iterator負責檢查迭代器的有效性:

  •  在迭代器遞增、遞減、解引用等操作的時候,檢查迭代器是否在vector的合法範圍內。
  •  兩個迭代器比較大小的時候,驗證它們迭代器是同一個vector的迭代器。

比如以下取值函數,就是檢查指針是否越界。

reference operator*() const

                {       // return designated object

 #if _ITERATOR_DEBUG_LEVEL == 2

                // 這裏檢查指針沒有越界

                if (this->_Getcont() == 0

                        || this->_Ptr == 0

                        || this->_Ptr < ((_Myvec *)this->_Getcont())->_Myfirst

                        || ((_Myvec *)this->_Getcont())->_Mylast <= this->_Ptr)

                        {       // report error

                        _DEBUG_ERROR("vector iterator not dereferencable");

                        _SCL_SECURE_OUT_OF_RANGE;

                        }

 

迭代器的單向鏈表

std::vector<_Ty,_Alloc>通過基類_Vector_val<_Ty,_Alloc>包含了一個_Container_proxy對象,_Container_proxy::_Myfirstiter指向了一個單向鏈表P的頭指針,P中包含一個vector對象的所有迭代器的指針。因此

  • 新建一個迭代器,需要向P的頭部插入一個指針,這是在常數時間完成的。
  • 銷燬一個迭代器,需要從P中刪除迭代器對應的指針。由於只保存了單向鏈表P的頭指針,這具有線性的時間複雜度(見下面的代碼)。如果一個容器的迭代器對象非常多,(比如hash_map的內部實現),則會非常耗時。

// 把迭代器指針從單向列表中刪除

        void _Iterator_base12::_Orphan_me()

                {       // cut ties with parent

 #if _ITERATOR_DEBUG_LEVEL == 2

                if (_Myproxy != 0)

                        {       // 從鏈表的頭指針向後遍歷,找到當前元素的前一個元素

                        _Iterator_base12 **_Pnext = &_Myproxy->_Myfirstiter;

                        while (*_Pnext != 0 && *_Pnext != this)

                                _Pnext = &(*_Pnext)->_Mynextiter;

 

                        if (*_Pnext == 0)

                                _DEBUG_ERROR("ITERATOR LIST CORRUPTED!");

                        *_Pnext = _Mynextiter;

                        _Myproxy = 0;

                        }

 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

                }

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章