Skąd się wzięło „wyjście (-1)”?

22

Widzę w dużo starszego oprogramowania i złych samouczków w Internecie, które zalecamy zastosowanie exit(-1), return -1lub podobny do reprezentowania „nieprawidłowe zakończenie”. Problem w tym, że przynajmniej w POSIX -1nigdy nie był i nie jest prawidłowym kodem statusu. man 3 exitilustruje, że exit()zwraca wartość elementu status & 0377nadrzędnego, co oznacza, że -1staje się 255. W systemach innych niż POSIX EXIT_FAILUREzaleca się przenośność. Ale nigdy nie widzę, że „-1 oznacza nieprawidłowe zakończenie” w połączeniu z „EXIT_FAILURE może być czymś innym niż 1”, co wskazuje, że wyraźnie wierzą, że „-1” jest konwencjonalne nawet w systemach innych niż POSIX.

Oto przykład pytania StackOverflow, które to utrwala. Oprogramowanie „unrealircd” jest także przykładem programu, który używa exit(-1)do zakończenia programu. W praktyce utrudnia to komunikację systemd.

Skąd wziął się ten anty-wzór? Czy jest ważny w jakimś kontekście?

użytkownik222973
źródło
1
„Systemy uniksowe mają silną konwencję, w której status wyjścia równy 0 oznacza sukces, a każdy niezerowy status wyjścia oznacza awarię ... Konwencja ta jest dość mocno połączona z powłokami uniksowymi ...” ( Niezerowy status wyjścia dla czystego wyjścia )
komara
@gnat Zgodnie z podręcznikiem libc status wyjścia jest jawnie od 0 do 255 włącznie. Jeśli gdzieś istnieje odpowiedź, która stwierdza, że ​​ujemne wartości były w pewnym momencie prawidłowe, zaakceptowałbym to, ale uważam to za bardzo wątpliwe.
user222973,
1
@gnat „255” łatwo mieści się w pliku unsigned char.
user222973,
1
@gnat Bajt w „Javie” nie jest znakiem bez znaku, jest bardziej równoważny, charponieważ jego zakres wartości wynosi od -128 do 127. Ponadto stwierdziłem, że „-1” jest konwertowane na „255” w moim ciele zapytania .
user222973,

Odpowiedzi:

20

Prawie wszystkie komputery z systemem Unix używają dopełniania dwójkowego dla liczb całkowitych, a w komplementarnych dwójkach -1 oznacza zawsze „wszystkie bity 1” niezależnie od wielkości słowa. Jeśli chcesz mieć możliwie największy kod wyjścia, niezależnie od wielkości statusu wyjścia programu, użyj -1 i pozostawienie biblioteki przyciętej wygodnie.

Jest to przydatne, ponieważ gdy skrypty lub programy mają więcej niż jeden możliwy status wyjścia (patrz grepprosty przykład), te znaczące są zwykle przypisywane do najmniejszych liczb, co sprawia, że ​​największy możliwy kod wyjścia jest dobry do użycia w przypadku „nieznanego błędu” lub „ przerwać ”, ponieważ jest mało prawdopodobne, aby kiedykolwiek wystąpił konflikt ze znaczącą wartością statusu.

Todd Knarr
źródło
Weźmy glibc jako przykład, który implementuje exit()jako status &= 0xff. Czy istnieje „rozmiar słowa”, w którym -1 & 0xffnie jest 255? Oczywiście, że nie, ponieważ głównym celem jest dopasowanie go w zakresie 0–255. Niezależnie od tego ostatnie zdanie nie ma sensu: kody statusu 128-255 mają specjalne zastosowanie w systemach UNIX.
user222973,
2
Nie należy mylić wartości wyjściowych Bash (które są 0-127, 128+ to specjalne wartości Bash) z wartościami wyjściowymi programu (które są 0-255, patrz pubs.opengroup.org/onlinepubs/009695399/functions/exit.html ). Jeśli chodzi o rozmiar, pamiętaj, że programiści C mieli do czynienia z wieloma rozmiarami słów (pierwotnie 12, 16 i 32 bity) od samego początku, więc automatycznie szukamy idiomów, które nie wymagają od nas rozważania rozmiaru słowa. Ponieważ Unix wyprzedza Posix o 2 dekady, nie zawsze było 8-bitowe ograniczenie, więc pisaliśmy, więc nie miało to znaczenia.
Todd Knarr