Как уже указывалось, поведение не определено .... но, несмотря на это, пытаясь оправдать наблюдаемое вами поведение, разработчики библиотек обычно склонны справляться со странным поведением программиста (например, , по крайней мере, странно). вызова exit()
, пока программа находится в exit()
) Я скажу:
Возможно, что функция exit(3)
перед вызовом любого из выходаобработчики, просто отменяет регистрацию из списка обработчиков сигналов.Это заставит функцию exit(2)
вызывать каждый обработчик выхода только один раз и не вызывать рекурсивный обработчик.Просто попробуйте зарегистрировать его снова, чтобы увидеть, что произойдет, было бы хорошим упражнением.
Возможно, что функция выхода помечает себя как выполняемую и, если она вызывается внутри обработчика, просто возвращает, как будто ничего не происходит.
Возможно, ваше ожидаемое поведение может привести к переполнению стака (здесь нет каламбура:))
Возможно ...
Что бы ни происходило, это часть UB, прокомментированная в других ответах, но для библиотеки, которая пытается расширить стандарт и вести себя нормально, вероятно, лучшее поведениечтобы избежать рекурсивных вызовов в обработчиках выхода некоторыми из предложенных способов.
С другой стороны, вам лучше не использовать эту функцию (давайте назовем так) в ваших программах, потому что, поскольку это не одобрено стандартом, может привести к проблемам, если вы перенесете свои программы в другое место в будущем.
Вы, вероятно, думаете о exit(3)
как о функции, которую никогда не следует вызывать дважды (кромеот рекурсивно, как вы разоблачаете), но вам кажется, что у вас есть несколько потоков в вашей программе, и два из них одновременно вызывают функцию exit(3)
.
Вероятно, наилучшим поведением будет иметь какой-то семафор, который позволяетобработчики должны быть защищены от взаимного доступа ... но лучший способ получить список обработчиков для кратковременного взлома - это отсоединить один обработчик от списка (давайте рассмотрим список как очередь, куда каждый поток приходит и берет обработчик)они получают обработчик, разблокируют очередь и затем выполняют ее.Это может привести к тому, что каждый обработчик выполняется одним потоком из тех, которые вызвали exit()
Первое, с чем сталкивается разработчик, это как работать с несколькими потоками, вызывающими exit()
одновременно.