Как указано в 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
вызывается в контексте потока, вызвавшего этот завершающий вызов?
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
после этого.
Других решений пока нет …