2017-09-15 98 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声明。

相关问题