在MSVC的调试模式下分配给std :: future时崩溃

Pat*_*ski 6 c++ future visual-c++

当使用MSVC在Debug模式下构建时,以下代码以随机间隔崩溃,不像Release.

#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);
}
Run Code Online (Sandbox Code Playgroud)

控制台输出说:

f:\ dd\vctools\crt\crtw32\stdcpp\thr\mutex.c(51):忙时销毁的互斥锁

完整的调用堆栈是:https://pastebin.com/0g2ZF5C1

现在显然它只是一个压力测试,但我做的事情是完全愚蠢的吗?在我看来,将新任务重新分配给现有的未来是可以的,因为它说operator=:

释放任何共享状态并移动 - 将其他内容分配给*this

(由于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);
}
Run Code Online (Sandbox Code Playgroud)

operator=本身不应该打电话wait吗?

背景:

_MSC_VER 等于 1911

代码是在以下帮助下构建的:

Microsoft Visual Studio Community 2017 Preview(2)
Version 15.4.0 Preview 2.0
Run Code Online (Sandbox Code Playgroud)

刚刚开设了一个全新的C++项目.

Xir*_*ema 1

自己不是operator=应该打电话吗wait

我不知道它是否应该如此,但粗略地浏览一下 MSVC15.3.4 的实现<future>似乎强烈表明它不应该如此。

//User Code
future f = /*...*/;
f = /*...*/; //(1)
Run Code Online (Sandbox Code Playgroud)
//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;
    }
Run Code Online (Sandbox Code Playgroud)

由于调用wait有助于同步事物并确保future对象处于可以修改的安全状态,因此最好包含该wait语句。