2017-09-15 146 views
6

Release不同,以下代碼在使用MSVC在Debug模式下構建時隨機間隔崩潰。在MSVC的調試模式下分配給std :: future時發生崩潰

#include <future> 

using namespace std; 

int main() { 
    auto l = [](){}; 
    auto f = async(launch::async, l); 

    for (int i = 0; i < 1000000; ++i) 
     f = async(launch::async, l); 
} 

控制檯輸出表示:

F:\ DD \ vctools \ CRT \ crtw32 \ stdcpp \ THR \ mutex.c(51):互斥破壞而 忙

完整的調用堆棧是:https://pastebin.com/0g2ZF5C1

現在顯然這只是一個壓力測試,但我做的事情完全是愚蠢的?在我看來,它的罰款,以重新分配新的任務到現有的未來,因爲它說,operator=

釋放任何共享狀態以及其他內容移動,分配給 *此

(由於http://en.cppreference.com/w/cpp/thread/future/operator%3D)。

它是MSVC的運行時錯誤嗎?

值得注意的是,如果我手動調用wait()轉讓之前,從而使循環進入程序停止崩潰:

for (int i = 0; i < 1000000; ++i) { 
    f.wait(); 
    f = async(launch::async, l); 
} 

是不是operator=本身應該調用wait

背景:

_MSC_VER等於1911

代碼與幫助下,內置:

Microsoft Visual Studio Community 2017 Preview(2) 
Version 15.4.0 Preview 2.0 

只是開放了一個全新的C++項目。

+0

確切版本的msvc和編譯器會很有用。 – Yakk

+0

只是一個猜測:有時候當你嘗試重新分配f時,有時可能仍然執行'l'。在調試中創建lambda的開銷可能比剩餘代碼的調試版本的開銷要大得多。這可以解釋它只發生在調試版本中。 –

+0

@Yakk當然,我編輯了這個問題。 –

回答

1

是不是operator=本身應該撥打wait

,我不知道是否應該,但在MSVC15.3.4實施<future>粗略地看一眼,似乎強烈建議事實並非如此。

//User Code 
future f = /*...*/; 
f = /*...*/; //(1) 
//MSVC Code 
future& operator=(future&& _Right) _NOEXCEPT //(1) 
    { // assign from rvalue future object 
    _Mybase::operator=(_STD move(_Right)); //(2) 
    return (*this); 
    } 
_State_manager& operator=(_State_manager&& _Other) //(2) 
    { // assign from rvalue _Other 
    _Move_from(_Other); //(3) 
    return (*this); 
    } 
void _Move_from(_State_manager& _Other) //(3) 
    { // move stored associated asynchronous state object from _Other 
    if (this != _STD addressof(_Other)) 
     { // different, move 
     if (_Assoc_state) 
      _Assoc_state->_Release(); //(4) 
     _Assoc_state = _Other._Assoc_state; 
     _Other._Assoc_state = 0; 
     _Get_only_once = _Other._Get_only_once; 
     } 
    } 
void _Release() //(4) 
    { // decrement reference count and destroy when zero 
    if (_MT_DECR(_Refs) == 0) 
     _Delete_this(); //(5) 
    } 
void _Delete_this() //(5) 
    { // delete this object 
    if (_Deleter) 
     _Deleter->_Delete(this); //External Code 
    else 
     delete this; 
    } 

看到,因爲調用wait同步上提供幫助的事情,並確保future對象是處於安全狀態進行修改,這可能是最好包括wait聲明。

相關問題