问题描述
在试图回答另一个Stackoverflow问题,我意识到,这个简单的C ++ 11片断隐含阻塞调用线程:
When trying to answer another Stackoverflow question, I realized that this simple C++11 snippet is implicitly blocking the calling thread:
std::async(std::launch::async, run_async_task)
对我来说这会是十分规范的C ++ 11发射任务异步,而无需关心结果的方式。相反,一个人必须显然明确创建和分离线程(见所提到的问题),以实现这一目标。
To me this would have seemed the canonical C++11 way to launch a task asynchronously without caring about the result. Instead one has to apparently explicitly create and detach a thread (see answer to mentioned question) in order to achieve this.
因此,这里是我的问题吗?那岂不是不够的,如果它放在 GET
块只否则,如果我不感兴趣的返回值或异常,它只是火,忘记?
So here's my question: Is there any reason in regards to safety/correctness that the destructor of a std::future
has to be blocking? Wouldn't it be enough if it blocks on get
only and otherwise, if I'm not interested in the return value or exception, it's simply fire and forget?
推荐答案
禁止通过和线程的的std ::异步的返回期货的析构函数:这是一个有争议的话题。以下按时间顺序论文名单反映了一些由委员会成员的讨论:
Blocking destructors of futures returned by std::async and of threads: That's a controversial topic. The following list of papers in chronological order reflects some of the discussions by the members of the committee:
- 的)由香草萨特
- 汉斯·贝姆
- 通过香草萨特
-
[..]为相关的在他们的析构函数
异步()
与异步
启动策略等待返回期货共享状态准备就绪。这prevents在相关线程继续运行的情况下,并没有更长的时间来等待它完成,因为相关的未来已经被破坏的一种手段。没有英雄的努力,否则等待完成,这样的失控线程可以继续过去它所依赖的对象的生命周期中运行。[..] Futures returned by
async()
withasync
launch policy wait in their destructor for the associated shared state to become ready. This prevents a situation in which the associated thread continues to run, and there is no longer a means to wait for it to complete because the associated future has been destroyed. Without heroic efforts to otherwise wait for completion, such a "run-away" thread can continue to run past the lifetime of the objects on which it depends.【例】
最终的结果很可能是一个跨线程记忆粉碎。这个问题当然是可以避免的,如果
的get()
或等待()
被称为[..]之前他们[期货]被破坏。困难[..]是一个意外的异常可能会导致code被绕过。因此,通常需要某种范围的后卫,以确保安全。如果程序员忘记添加范围后卫,看来有可能使攻击者可以如产生在一个适当的点bad_alloc异常趁监督,并造成堆栈被覆盖。它可能也控制用于覆盖堆栈中的数据,并因此获得对过程的控制。这是一个微妙的足够错误,根据我们的经验,这很可能在现实code被忽视。The end result is likely to be a cross-thread "memory smash". This problem is of course avoided if
get()
orwait()
is called [..] before they [the futures] are destroyed. The difficulty [..] is that an unexpected exception may cause that code to be bypassed. Thus some sort of scope guard is usually needed to ensure safety. If the programmer forgets to add the scope guard, it appears likely that an attacker could generate e.g. a bad_alloc exception at an opportune point to take advantage of the oversight, and cause a stack to be overwritten. It may be possible to also control the data used to overwrite the stack, and thus gain control over the process. This is a sufficiently subtle error that, in our experience, it is likely to be overlooked in real code.更新:光良的旅行报告的还包含有关会议的结果2013年9月一些有趣的信息:
Update: Michael Wong's Trip Report also contains some interesting information regarding the outcomes of the meeting in September 2013:
<一个href=\"https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/the_view_from_the_c_standard_meeting_september_2013_part_2?lang=en\">The查看从C ++标准会议2013年9月第2。2
在这个问题的异步析构函数不应该阻止我们专门讨论了很大的就可以了。 [..]是得到广泛支持的唯一位置就是[..]给咨询,未来的析构函数不会阻止,除非异步返回,使得它的显着的例外。 [..]后显著的讨论,我们试图携带的唯一部分是N3776,试图澄清的立场是
〜未来
和〜shared_future
除了可能在异步的presence不阻止。有发行沿着C.德precate异步电动机无需更换线一德precation的尝试。这个运动实际上几乎提出。但是,[..]它甚至它达到了手术台前就去世了。On the issue that async destructors should not block we devoted a great deal of discussion on it. [..] The only position that received considerable support was [..] giving advisory that future destructors will not block, unless returned from async, making it the notable exception. [..] After significant discussion, the only part that we tried to carry was N3776, an attempt to clarify the position that
~future
and~shared_future
don’t block except possibly in the presence of async. There was an attempt to issue a deprecation along the lines of C. Deprecate async without replacement. This motion was actually almost put forward. But [..] it died even before it reached the operating table.这篇关于为什么从`性病::返回async`阻止未来的析构函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!