Всегда ли неправильно завершать вызывающую программу (например, call exit ()) из библиотеки, когда вместо нее может быть возвращена ошибка / исключение? - PullRequest
1 голос
/ 19 сентября 2019

Я всегда считал, что ответ будет однозначным: да .

Вчера я написал следующее в комментарии на reddit.com / r/ c_programming :

Завершение вызывающей программы внутри библиотеки является серьезным нарушением разделения интересов: библиотека несет ответственность за возвращение результата, будь то ожидаемый результат или ошибка, ничегобольше, не меньше;в то время как вызывающий абонент несет ответственность и прерогативу делать с этим результатом все, что сочтет лучшим.

Однако, к моему удивлению, я не смог найти никаких вопросов по переполнению стека или Программная инженерия , которая напрямую решает эту довольно фундаментальную проблему.

Если этот вопрос не является дубликатом, я полагаю, что было бы полезно, если бы он послужил будущим ориентиром в этом отношении - в надеждесм. некоторые убедительные аргументы, официальные указания или иные авторитетные источники.

1 Ответ

1 голос
/ 19 сентября 2019

На этот вопрос трудно ответить, потому что не подходит размер 1 для всех.

Первая проблема, которая может возникнуть, если плагин / библиотека преждевременно выйдет из программы, состоит в том, что она остановит программу.прежде чем какая-либо очистка может быть выполнена программой, обычно закрывающейся.Так что, если программа не использует хуки, такие как atexit, on_exit.Вполне возможно, что программа закроется в неопределенном состоянии.

Все функции, зарегистрированные с помощью atexit (3) и on_exit (3), вызываются в обратном порядке их регистрации.(Одна из этих функций может использовать atexit (3) или on_exit (3) для регистрации дополнительной функции, которая будет выполняться во время обработки выхода; новая регистрация добавляется в начало списка функций, которые еще предстоит вызвать.) Если одна из этих функций не возвращает (например, вызывает _exit (2) или убивает себя с помощью сигнала), то не вызывается ни одна из оставшихся функций, и происходит дальнейшая обработка выхода (в частности, сброс stdio (3).Потоки) заброшен.Если функция была зарегистрирована несколько раз с помощью atexit (3) или on_exit (3), то она вызывается столько раз, сколько была зарегистрирована.

http://man7.org/linux/man-pages/man3/exit.3.html

Другая проблема заключается в том, что некоторые программы полагаются на некоторые конкретные коды выхода, поэтому, если программа завершает работу с exit(0), она должна выйти, потому что программа завершилась нормально, в противном случае ей следует использовать какой-то код завершения, который имеет смысл для программы.

Если программа реализует правильно выходящие обратные вызовы, было бы не страшно использовать exit напрямую, предполагая, что программа может выполнять очистки.

С другой стороны, если программа предоставляет некоторые API для выхода изпрограмма должна использоваться вместо непосредственного выхода.

Так что действительно зависит от того, будет ли программа обрабатывать "выходящие" ситуации.

Но если мы говорим о библиотеке, подобной библиотеке NFCReader... или что-то общее, что не связано с основной программой.Это было бы странно и, возможно, раздражало бы иметь библиотеку, которая заставила бы вашу программу умереть в случаях, когда ошибки не являются неисправимыми.

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

Представьте себе, что библиотека регулярных выражений используется в некоторых медицинскихоборудование, которое в каком-то странном сценарии не сможет проанализировать регулярное выражение и решить выйти из программы в середине операции.

...