2017-09-15 10 views
6

Releaseとは異なり、DebugモードでMSVCを使用してビルドすると、次のコードがランダムな間隔でクラッシュします。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のランタイムのバグですか?私は手動ためにループを作り、割り当ての前に()の待機を呼び出す場合

驚くべきことに、プログラムがクラッシュを停止する:

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

自体がwaitを呼び出すことになってoperator=ませんか?コードはの助けを借りて建設された1911

_MSC_VER等しい:

背景

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

ただ、ブランドの新しいC++プロジェクトを開きました。

+0

正確なバージョンのmsvcとコンパイラが便利です。 – Yakk

+0

ちょうど推測:あなたがfを再割り当てしようとしているうちに、たぶん 'l'が実行されていることがあります。おそらく、デバッグ時にラムダを作成するオーバーヘッドは、残りのコードのデバッグバージョンのオーバーヘッドに比べてはるかに大きくなります。これは、デバッグバージョンでのみ発生することを説明することができます。 –

+0

@ヤク確かに、私は質問を編集しました。 –

答えて

1

operator=は、waitと呼ぶはずですか?

私はそれがへなっであるかどうかわからないが、<future>のMSVC15.3.4実装でチラッと見が強く、それがない示唆しているようです。 waitを呼び出すと見

//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オブジェクトが変更されるように安全な状態にあることを確認できます。

関連する問題