2015-11-13 55 views
4

我剛纔讀this文章關於當前boost::mutex實現背後的實際原因,發現下面的語句:塊範圍靜態的析構函數可以被調用多次?

塊範圍靜有關於「第一次通過」一個潛在的比賽 條件的其他問題,這可能導致 析構函數在流行的編譯器上運行多次,即 未定義的行爲 - 編譯器通常使用相當於調用 atexit的方法,以確保以反向 構建的順序完成銷燬,並且初始化競爭可能會導致 構造函數運行兩次也可能造成析構函數爲 註冊兩次

這是真的嗎?我是否應該通過原子操作或類似的東西來檢查另一個線程是否已經在這個對象的析構函數中?我應該這樣做,即使在C++ 11 - C++ 14中?因爲據我所知,自從C++ 11以來,沒有更多的「具有靜態存儲的同一本地對象的構造函數可以從多個線程同時調用」的問題 - 它要求另一個線程應該等待構造函數的完成。我對嗎?

回答

2

它看起來像我寫這篇文章前C++ 11,它說,除其他事項外:

[...]下一個版本的C++標準,計劃於2009年[發佈。 ..]

這是Pre C++ 11的情況,在這種情況下沒有指定發生了什麼,因爲線程不是內存模型pre C++ 11的一部分。

這改變了C++ 11和draft C++11 standard部分6.7聲明語句說(重點煤礦):

零初始化(8.5)的靜態所有塊範圍變量 存儲持續時間(3.7.1)或線程存儲持續時間(3.7.2)是 在任何其他初始化發生之前執行。 [...]否則 這樣一個變量初始化時第一次控制通過 其聲明;這樣的變量在其初始化完成時被認爲初始化。如果初始化退出 引發異常,則初始化未完成,因此在下一次控制進入聲明時將再次嘗試 。 如果 控制同時進入聲明,而變量是 被初始化,併發執行應等待完成 的初始化。 [...]

Pre C++ 11我們必須像處理其他關鍵部分一樣對待靜態局部變量。我們可以在C++ scoped static initialization is not thread-safe, on purpose!之後找到關於pre-C++ 11的一個很好的描述。

+0

如何競爭條件影響靜態變量的破壞pre-C++ 11?編譯器不是負責清理靜態對象的任何線程? – user2079303

+1

@ user2079303如果多個實例化完成,那麼你可能會得到多個析構函數調用。由於該標準沒有指定多線程內存模型,因此實現可以以任何可能的方式自由處理這種情況。 –

+0

我們應該如何處理它的情況下的前C + + 11? – FrozenHeart

相關問題