Должна ли пользовательская функция terminate () быть поточно-ориентированной?

Как указано в http://en.cppreference.com/w/cpp/error/terminate Есть много причин, чтобы позвонить, прекратить. Я могу представить себе случай, когда почти в одно и то же время некоторые из этих причин происходят в двух потоках.

Q1 Может ли прекратить функцию, установленную std::set_terminate быть вызванным дважды или более одновременно, к тому же времени я имею в виду, что второй вызов начинается до того, как первый закончился.

  Thread1   Thread2
|          |
_          |
t          |
e          |
r          |
m          |
i          _
n          t
a          e
t          r
e          m
-          ?

Q2 Если Q1 == ДА, то, что произойдет, если закончится первое завершение. Я предполагаю, что если он закончился с помощью std :: abort, то программа завершается, но что произойдет, если пользовательское завершение не прервет программу?

Q3 Функция завершения установлена std::set_terminate вызывается в контексте потока, вызвавшего этот завершающий вызов?

11

Решение

Q1

Да, std::terminate может быть вызван одновременно.

Q2

Стандарт говорит, что это неопределенное поведение для terminate_handler не «прекратить выполнение программы без возврата к вызывающей стороне». В реализациях, с которыми я знаком, если terminate_handler пытается вернуться, либо нормально, либо в исключительных случаях, abort() будет называться.

Q3

Функция устанавливается std::terminate является глобальным, а не локальным потоком. Так что один поток может повлиять на другой.

В C ++ 98/03 terminate_handler используется когда terminate вызывается из-за неперехваченного исключения — это то, которое действовало, когда возникло исключение, а не то, которое действовало, когда terminate на самом деле называется (хотя они обычно одинаковы).

В C ++ 11 это было изменено, и теперь в стандарте говорится, что используемый в данный момент обработчик terminate называется. Это изменение было сделано по ошибке и, скорее всего, будет исправлено в будущем проекте. Вот проблема LWG, отслеживающая эту проблему:

http://cplusplus.github.com/LWG/lwg-active.html#2111

Обновить

На встрече весной 2015 года в Ленексе, штат Калифорния, LWG решила стандартизировать существующее поведение и сделала его неопределенным, когда новый terminate_handler вступает в силу, если set_terminate вызывается при разматывании стека. То есть реализациям разрешено следовать либо правилам C ++ 98/03, либо правилам C ++ 11.

Чтобы сделать ваш код переносимым, если вам нужно установить terminate_handlerделайте это во время запуска программы, прежде чем будут сгенерированы какие-либо исключения, и не вызывайте привычку set_terminate после этого.

7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]