给定以下源代码
#include <thread>
#include <future>
#include <iostream>
#include <string>
#include <chrono>
int main() {
auto task = std::async(std::launch::async, [] {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
throw std::runtime_error("error");
});
try {
while (task.wait_for(std::chrono::seconds(0)) !=std::future_status::ready)
{
std::cout << "Not ready: " << std::endl;
}
task.get();
}
catch (const std::exception& e)
{
std::cout << "Valid: " << task.valid() << std::endl;
}
}
我希望程序会以 Valid: 0
响应。使用 g++ 6.2.0 就是这种情况。但是,使用 MS VS2015 版本 14.0.25431.01 更新 3,响应为 Valid: 1
。在异常传播到主线程后, future 的状态不会失效。这是一个错误还是我在这里遇到未定义的行为?
最佳答案
我好像是个 bug 。
根据 std::future::get
documentation , valid()
应在调用 get
后返回 false
。
Any shared state is released.
valid()
isfalse
after a call to this method.
深入研究 get
的 VC++ 实现,那里有一个错误:
virtual _Ty& _Get_value(bool _Get_only_once)
{ // return the stored result or throw stored exception
unique_lock<mutex> _Lock(_Mtx);
if (_Get_only_once && _Retrieved)
_Throw_future_error(
make_error_code(future_errc::future_already_retrieved));
if (_Exception)
_Rethrow_future_exception(_Exception);
_Retrieved = true;
_Maybe_run_deferred_function(_Lock);
while (!_Ready)
_Cond.wait(_Lock);
if (_Exception)
_Rethrow_future_exception(_Exception);
return (_Result);
}
基本上,如果 _Exception
持有 exception_ptr
,则 _Retreived
也应设置为 true
。到抛出时,此变量从未设置。看起来当他们测试它时,他们并没有为一个现成的 future 而测试,
仅适用于未就绪的 future ,因为后者不会显示此错误。
关于c++ - std::futures 和异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42648352/