天天看點

vector問題總結

1.vector iterators incompatible

發現引發這個錯誤的代碼如下:

for (VectorType::iterator it = someVector.begin();; it != someVector.end();++it;)

{

    if (*it== value)

    {

        someVector.erase(it);

    }

}

代碼中,在erase操作後,沒有修改it就繼續循環,在與end()比較時,斷言出現。

這裡的主要問題是,vector可以用任意方法實作erase,不保證在erase一個元素後,後續的元素一定被移動到這個iterator所引用的位置(位址)。當然,這在幾乎所有STL的實作中,都是對的,這也就是以前用VC6編譯後運作沒有問題的原因。但如果這裡用的不是vector,而是list或是map,運作到這裡,程式會毫不猶豫的崩潰。

正确的做法是這樣的:

STL裡所有的容器類的erase實作都會傳回一個iterator,這個iterator指向了“目前删除元素的後繼元素,或是end()”

是以,在周遊容器的所有元素過程中通過erase删除一個元素後,将erase的傳回值賦給疊代變量:

for (VectorType::iterator it = someVector.begin();; it != someVector.end();)

{

    if (*it== value)

    {

        it = someVector.erase(it);

    }

    else

    {

        ++it;

    }

}

P.S. 可以看出,VS2005帶的STL增加了更多的調試特性以避免出現STL的一些錯誤,有條件的話最好用VS2005的STL。如果沒有VS2005,也可以使用STLport,STLport在調試特性上也非常出色。

如果你要略過這個檢查,可以用#define _HAS_ITERATOR_DEBUGGING 0 不過建議還是檢查線程的同步代碼。

2.空Vector問題。不允許引用空vector的begin疊代器,因為vector是空的,自然不會有第一個項目,使用也會引發vector iterators incompatible。

3.vector同時讀寫引發。vc2005 對于疊代器的比對是非常嚴格的,通常這種錯誤是因為兩個不同的疊代器操作同一個 vector,或者是因為疊代器在周遊vector時,vector的連結清單改變了,就會引發這種錯誤,比如vector在周遊的途中,别的位置push_back()一個元素,這時疊代器就失效了,導緻錯誤。可以使用臨界區互斥通路。

4.疊代器越界,則相應會調用一個非法參數處理程式。

再次提醒,可以通過抛出一個越界異常來避免産生非法參數問題。在代碼中加入#define value of _SECURE_SCL_THROWS,并把value值設為1,這樣就不會調用非法參數處理程式,而是産生一個異常了。

也可以通過設定#defined value of _SECURE_SCL值為零,關閉此疊代器檢查,通常預設情況下,此選項是打開的。

5.VS2005編譯Release版STL的疊代器bug。經測試Unicode版的比較容易出這個問題,就是莫名其妙的疊代器錯誤。

微軟的原文:The bug afflicted all Standard containers (vector, deque, list, set, multiset, map, multimap, and string) when _HAS_ITERATOR_DEBUGGING was disabled and _SECURE_SCL was enabled. Additionally, deque was afflicted when both were disabled.解決辦法是

#ifndef _DEBUG

#define _SECURE_SCL 0

#endif