vector在多線程下的問題(轉)


  最近在做項目的過程中,遇到STL中vector的多線程訪問問題。問題大概是這樣的:有一個全局的vector,一個寫進程對該vector進行插入操作(push_back()),同時有一個讀進程在監視該vector的內容並對其進行顯示(操作:size(), at(i)),沒有進行任何的線程同步,程序的編譯沒有任何問題,卻一直出現運行時錯誤,主要是數組越界。  當時的考慮時:雖然vector不支持多線程,但是我的兩個線程,一個寫,一個卻是只讀,按理說不應該有問題,大不了有臟數據,但是我不在乎。網上有很多人說是線程同步問題,但是個人感覺不是這個問題。后來看了一篇網文之后才晃然大悟,其實是vector的大小動態分配所造成的問題。簡單的說就是讀進程和寫進程在vector的內存動態重分配時內存地址不同步了(不知道說的對不對)。懶的再描述自己的具體問題了,直接把那篇網文貼上來,以供以后查看。

 

原文地址http://donghao.org/2008/10/vectorouaissiiaaieia.html

原文內容:

  程序出現了coredump,用gdb發現了出錯的地方。

vector<size_t> seq_offset;
......
if(seq_id < seq_offset.size())
{
    seq_offset[seq_id];        //此處coredump
}

      沒有超過vector的大小,訪問是不應該有問題的,而且這一現象是偶然出現,所以懷疑是多線程的原因。果然在另一個線程里發現對seq_offset有 insert操作,insert本身不會影響訪問,但是當vector大小不夠的時候,insert會引發內存重新分配。STL代碼(linux gcc-3.4.3 /usr/include/c++/3.4.3/bits)里,vector的insert會調用_M_fill_insert,而當空間不夠時 _M_fill_insert會重新分配空間,並將相關數據結構指向新空間。

文件 vector.tcc 
324        std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish);        //銷毀vector里的元素,即調用各元素的析構函數
325         _M_deallocate(this->_M_impl._M_start,                                           //收回存放各元素的空間,即free
326               this->_M_impl._M_end_of_storage - this->_M_impl._M_start);        
327         this->_M_impl._M_start = __new_start.base();                                //數據結構指向新的空間
328         this->_M_impl._M_finish = __new_finish.base();              
329         this->_M_impl._M_end_of_storage = __new_start.base() + __len;

      麻煩就在於當326行結束后,_M_start指向的是一塊已經釋放了的空間,這時候再有vector的訪問操作(如 seq_offset[seq_id])當然就會coredump。其實STL完全可以先把_M_start賦給一個臨時變量,然后_M_start指向 新空間,最后再釋放臨時變量指向的空間,這樣可以保證在多線程下順利運行。不過STL文檔說了——它不支持多線程——所以這樣做也沒錯。
      加鎖也可以解決這個問題,不過那樣太低效了,不予考慮。最后的解決方案是,用vector的reserve方法預先分配好內存,免得在使用中動態增長。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM