Откуда взялся «выход (-1)»?

22

Я вижу в много унаследованного программного обеспечения и плохие учебники в Интернете , который рекомендуется использовать exit(-1), return -1или сходного представлять «аварийное завершение». Проблема, по крайней мере, в POSIX, -1никогда не была и не является допустимым кодом состояния. man 3 exitиллюстрирует, что exit()возвращает значение status & 0377для родителя, что означает, что -1становится 255. В системах без POSIX EXIT_FAILUREрекомендуется для переносимости. Но я никогда не вижу, что «-1 означает ненормальное завершение» в сочетании с «EXIT_FAILURE может быть чем-то отличным от 1», что указывает на то, что они явно полагают, что «-1» является обычным даже в системах, отличных от POSIX.

Вот пример вопроса StackOverflow, который увековечивает это. Программное обеспечение "unrealircd" также является примером программы, которая используется exit(-1)для завершения программы. На практике это затрудняет взаимодействие systemd.

Откуда взялся этот анти-паттерн? Это действительно в каком-то контексте?

user222973
источник
1
«У Unix-подобных систем есть строгое соглашение, что состояние выхода 0 означает успех, а любое ненулевое состояние выхода означает сбой ... Это соглашение в значительной степени встроено в оболочки Unix ...» ( Ненулевое состояние выхода за чистый выход )
комнат
@gnat Согласно руководству по libc, статус выхода явно от 0 до 255 включительно. Если где-то есть ответ, в котором говорится, что отрицательные значения в какой-то момент действительны, я бы это принял, но я нахожу это весьма сомнительным.
user222973
1
@gnat "255" легко вписывается в unsigned char.
user222973
1
@gnat Байт в «Java» не является беззнаковым символом, он более эквивалентен a, charпоскольку его диапазон значений составляет от -128 до 127. Кроме того, я уже говорил, что «-1» преобразуется в «255» в моем теле вопроса ,
user222973

Ответы:

20

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

Это полезно, потому что когда сценарии или программы имеют более одного возможного состояния выхода (см. grepПростой пример), значимые из них обычно присваиваются наименьшим числам, что делает максимально возможный код выхода хорошим для использования при «неизвестной ошибке» или « прервать », так как это вряд ли когда-либо вступит в конфликт со значимым значением статуса.

Тодд Кнарр
источник
Возьмите в качестве примера glibc, который реализует exit()как status &= 0xff. Есть ли «размер слова», в котором -1 & 0xffнет 255? Конечно, нет, потому что вся цель состоит в том, чтобы сделать его подходящим в диапазоне 0-255. В любом случае, ваше последнее предложение не имеет смысла: коды состояния 128-255 имеют специальное назначение в системах UNIX.
user222973
2
Не путайте значения выхода Bash (которые 0-127, 128+ являются специальными значениями Bash) со значениями выхода программы (которые 0-255, см. Pubs.opengroup.org/onlinepubs/009695399/functions/exit.html ). Что касается размера, помните, что программисты на C имели дело с несколькими размерами слов (изначально 12, 16 и 32 бита) с самого начала, поэтому мы автоматически пытаемся найти идиомы, которые не требуют от нас учета размера слова. Так как Unix предшествовал Posix на 2 десятилетия, не всегда было 8-битное ограничение, поэтому мы писали так, что это не имело значения.
Тодд Кнарр