Ответ 1
Блокировка деструкторов фьючерсов, возвращаемых std:: async и потоков: это спорная тема. Следующий список документов в хронологическом порядке отражает некоторые из обсуждений членами комитета:
- N2802: просьба пересмотреть отказ от уничтожения для объектов потоков Hans Boehm
- N3630: async, ~ future и ~ thread (версия 1) от Herb Sutter
- N3636: ~ поток должен присоединиться от Herb Sutter
- N3637: async и ~ future (версия 3) Херб Саттер, Чандлер Каррут, Никлас Густафссон
- N3679: Async() будущие деструкторы должны ждать Hans Boehm
- N3773: async и ~ future (версия 4) Херб Саттер, Чандлер Каррут, Никлас Густафссон
- N3776: формулировка для будущего Herb Sutter
- N3777: формулировка для устаревания async Herb Sutter
Несмотря на то, что было много обсуждений, для С++ 14 не запланировано никаких изменений в отношении поведения блокировки деструкторов std:: future и std:: thread.
Что касается вашего вопроса, самая интересная статья, вероятно, вторая - Хансом Бёмом. Я цитирую некоторые части, чтобы ответить на ваш вопрос.
N3679: ожидающие деструкторы Async() должны ждать
[..] Фьючерсы, возвращаемые
async()
с политикой запускаasync
, ждут в своем деструкторе, чтобы связанное с ним состояние стало готовым. Это предотвращает ситуацию, когда связанный поток продолжает работать, и больше не существует способа дождаться завершения, потому что связанное будущее было уничтожено. Без героических усилий, чтобы иначе ждать завершения, такой поток "бежать" может продолжать работать за время жизни объектов, от которых он зависит.[Пример]
Конечный результат, скорее всего, будет "потоком памяти" с перекрестной резьбой. Разумеется, эту проблему избегают, если
get()
илиwait()
вызывается [..], прежде чем они [фьючерсы] будут уничтожены. Трудность [..] заключается в том, что неожиданное исключение может привести к обходу этого кода. Таким образом, для обеспечения безопасности обычно требуется какой-то контроль степени. Если программист забыл добавить защитную систему области видимости, представляется вероятным, что злоумышленник может генерировать, например. исключение bad_alloc в подходящей точке, чтобы воспользоваться надзором и вызвать перезапись стека. Возможно также управлять данными, используемыми для перезаписи стека, и таким образом получить контроль над процессом. Это достаточно тонкая ошибка, которая, по нашему опыту, скорее всего, будет упущена в реальном коде.
Обновление: Отчет о поездке Майкла Вона также содержит интересную информацию об итогах встречи в сентябре 2013 года:
Вид со стандартного собрания С++ Сентябрь 2013 г. Часть 2 из 2.
В связи с тем, что асинхронные деструкторы не должны блокировать, мы посвятили большое обсуждение этого вопроса. [..] Единственная позиция, которая получила значительную поддержку, была [..], давая советы о том, что будущие деструкторы не будут блокироваться, если они не возвращаются из async, что делает его заметным исключением. [...] После значительного обсуждения единственной частью, которую мы пытались перенести, была N3776, попытка прояснить позицию, которую
~future
и~shared_future
не блокировать, за исключением, возможно, наличия асинхронизации. Была предпринята попытка выпустить устаревшую версию в строках C. Запретить асинхронную замену без замены. Это движение было фактически выдвинуто. Но [...] он умер еще до того, как он достиг операционного стола.