我对std :: promise的VC ++实现(Visual Studio 2015和2017)都有一个奇怪的问题。 set_value_at_thread_exit()似乎不像宣传的那样工作 - 或者我误解了标准允许的内容以及标准不允许的内容。以下代码将在clang中编译并运行正常,但在使用VS2015(在第二个块中)或VS2017(在第三个块中)编译时会崩溃:
#include <future>
#include <thread>
#include <iostream>
int main()
{
{
std::cout << "Safe version... ";
std::promise<int> promise;
auto f = promise.get_future();
std::thread
(
[](std::promise<int> p)
{
p.set_value(99);
},
std::move(promise)
)
.detach();
std::cout << f.get() << std::endl;
}
{
std::cout << "Will crash VS2015... ";
std::promise<int> promise;
auto f = promise.get_future();
std::thread(
[p{ std::move(promise) }]() mutable
{
p.set_value_at_thread_exit(99);
}
)
.detach();
std::cout << f.get() << std::endl;
}
{
std::cout << "Will crash VS2017... ";
std::promise<int> promise;
auto f = promise.get_future();
std::thread(
[](std::promise<int> p)
{
p.set_value_at_thread_exit(99);
},
std::move(promise)
)
.detach();
std::cout << f.get() << std::endl;
}
}
我试图通过慷慨地使用换行符来显示差异。
问题似乎是在MS实现中,lambda函数内的promise对象的析构函数尝试使用“破坏的承诺”来更新共享状态。即使调用了set_value_at_thead_exit()也是异常。但是,这会失败并依次抛出系统错误。它在尝试锁定关联的互斥锁时发生。 如果未调用set_value_at_thread_exit(),则f.get()将按预期抛出future_error。
查看MS实现(VS2017),我发现代码假装检查共享状态是否在线程退出时就绪,但什么也没做。所以我想知道这是一个错误,还是我误解了API,我应该确保承诺的生命周期延伸到线程退出之外。
后者似乎是VS2017在第二个代码块中发生的事情,但在VS2015中却没有 - 可能是由于std :: thread的实现差异?!
如上所述,代码在
中运行良好 clang:http://rextester.com/FEZDS24592
gcc:http://rextester.com/WFKE61563
但在
中崩溃 VS2015中的第二个区块:http://rextester.com/NODVFO14840
和VS2017中的第三个块。这可以在这里测试:http://webcompiler.cloudapp.net/
所以基本上我想知道我是否应该提出一个问题,或者我是不是会自欺欺人,因为我使用的语言都错了?
由于
答案 0 :(得分:0)
事实证明,xxx_at_thread_exit()在大多数当前实现中都存在问题。有关详细信息,请参阅this visual studio community issue。