问题 std :: future会在销毁时调用wait()或get()吗?
示例
void fun()
{
std::future<int> fut = my_thread_pool.submit(some_work);
}//is fut.wait() or fut.get() called? here
答案 0 :(得分:3)
来自:The View from the C++ Standard meeting September 2013 Part 2 of 2.
关于异步析构函数不应该阻止的问题,我们投入了一个 关于它的大量讨论。 [...] 收到的唯一立场 相当大的支持是[...]提供未来析构者的咨询 不会阻止,除非从异步返回,使其成为值得注意的 例外。 [..]经过重大讨论,我们唯一的一部分 试图携带的是N3776,试图澄清其立场 〜将来和~socred_future除非可能存在,否则不会阻止 异步。曾试图沿着这条线发布弃用 C.无需替换即可弃用异步。这个动议实际上是 几乎提出来了。但是[..]它甚至在它到达之前就已经死了 手术台。
同时检查:N3679: Async() future destructors must wait
基本问题
async()返回的期货与异步启动策略等待 用于关联共享状态的析构函数。这个 防止关联线程继续运行的情况, 并且不再有等待它完成的手段,因为 相关的未来已被破坏。没有英勇的努力 否则等待完成,这样的&#34;逃跑&#34;线程可以继续 超过它所依赖的对象的生命周期。
例如,考虑以下一对功能:
void f() { vector<int> v; ... do_parallel_foo(v); ... } void do_parallel_foo(vector<int>& v) { auto fut = no_join_async([&] {... foo(v); return ...; }); a: ... fut.get(); ... }
如果no_join_async()返回析构函数不等待的未来 异步完成,一切都可能正常,直到抛出的代码 一个例外。那时没有等待异步完成, 它可能继续从do_parallel_foo()的出口运行 和f(),导致异步任务访问和覆盖内存 以前分配给v超过它的一生。
最终结果很可能是一个跨线程&#34;内存粉碎&#34;类似 在类似条件下在N2802中描述的那种。
如果调用get()或wait(),当然可以避免这个问题 no_join_async() - 在销毁之前生成的期货。该 难度,如在N2802中,是一个意外的异常可能导致 要绕过的代码。因此通常会有某种范围的守卫 需要确保安全。如果程序员忘记添加范围 警卫,似乎攻击者可能会产生例如一个 bad_alloc异常在适当的时候利用了 疏忽,并导致堆栈被覆盖。有可能 还控制用于覆盖堆栈的数据,从而获得增益 控制过程。这是一个足够微妙的错误,在 根据我们的经验,它可能会在实际代码中被忽略。