在MSVC的调试模式下分配给std :: future时发生崩溃
问题描述:
与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++项目。
答
是不是
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
声明。
确切版本的msvc和编译器会很有用。 – Yakk
只是一个猜测:有时候当你尝试重新分配f时,有时可能仍然执行'l'。在调试中创建lambda的开销可能比剩余代码的调试版本的开销要大得多。这可以解释它只发生在调试版本中。 –
@Yakk当然,我编辑了这个问题。 –