Jaka jest różnica między exit()
i w językach C i C ++ abort()
? Próbuję zakończyć program po błędzie (nie jest to wyjątek).
Jaka jest różnica między exit()
i w językach C i C ++ abort()
? Próbuję zakończyć program po błędzie (nie jest to wyjątek).
Odpowiedzi:
abort()
zamyka program bez wywoływania funkcji zarejestrowanych jako atexit()
pierwsze i bez uprzedniego wywoływania destruktorów obiektów. exit()
robi obie te rzeczy przed wyjściem z programu. Nie wywołuje jednak destruktorów dla obiektów automatycznych. Więc
A a;
void test() {
static A b;
A c;
exit(0);
}
Zniszczy a
i b
poprawnie, ale nie wywoła destruktorów c
. abort()
nie nazwałby destruktorów żadnego z obiektów. Ponieważ jest to niefortunne, w standardzie C ++ opisano alternatywny mechanizm zapewniający prawidłowe zakończenie:
Obiekty z automatycznym czasem trwania są niszczone w programie, którego funkcja
main()
nie zawiera automatycznych obiektów i wykonuje wywołanieexit()
. Kontrolę można przekazać bezpośrednio do takiegomain()
, rzucając wyjątek, który jest przechwytywanymain()
.
struct exit_exception {
int c;
exit_exception(int c):c(c) { }
};
int main() {
try {
// put all code in here
} catch(exit_exception& e) {
exit(e.c);
}
}
Zamiast dzwonić exit()
, zaaranżuj ten kod throw exit_exception(exit_code);
.
abort wysyła sygnał SIGABRT, exit zamyka tylko aplikację wykonującą normalne czyszczenie.
Możesz obsłużyć sygnał przerwania , jak chcesz, ale domyślnym zachowaniem jest zamknięcie aplikacji również z kodem błędu.
abort nie spowoduje zniszczenia obiektów statycznych i globalnych członków, ale zakończy działanie .
Oczywiście, gdy aplikacja zostanie całkowicie zamknięta, system operacyjny zwolni niewykorzystaną pamięć i inne zasoby.
Zarówno w przypadku przerwania, jak i zakończenia programu wyjściowego (zakładając, że nie nadpisałeś domyślnego zachowania), kod powrotu zostanie zwrócony do procesu nadrzędnego, który uruchomił Twoją aplikację.
Zobacz poniższy przykład:
SomeClassType someobject;
void myProgramIsTerminating1(void)
{
cout<<"exit function 1"<<endl;
}
void myProgramIsTerminating2(void)
{
cout<<"exit function 2"<<endl;
}
int main(int argc, char**argv)
{
atexit (myProgramIsTerminating1);
atexit (myProgramIsTerminating2);
//abort();
return 0;
}
Uwagi:
Jeśli abort nie jest komentowany: nic nie jest drukowane, a destruktor jakiegoś obiektu nie zostanie wywołany.
Jeśli abort jest komentowane jak powyżej: zostanie wywołany jakiś destruktor obiektów, otrzymasz następujący wynik:
wyjście z funkcji 2
wyjście z funkcji 1
Następujące rzeczy mają miejsce, gdy program wywołuje exit
():
atexit
funkcjętmpfile
są usuwaneFunkcja abort
() wysyła SIGABRT
sygnał do bieżącego procesu, jeśli nie zostanie przechwycony, program zostanie zakończony bez gwarancji, że otwarte strumienie zostaną opróżnione / zamknięte lub że pliki tymczasowe utworzone za pomocą tmpfile
zostaną usunięte, atexit
zarejestrowane funkcje nie zostaną wywołane, a zerowy kod wyjścia jest zwracany do hosta.
Ze strony podręcznika exit ():
Funkcja exit () powoduje normalne zakończenie procesu, a wartość statusu & 0377 jest zwracana do rodzica.
Ze strony podręcznika abort ():
Abort () najpierw odblokowuje sygnał SIGABRT, a następnie podnosi ten sygnał dla procesu wywołującego. Powoduje to nieprawidłowe zakończenie procesu, chyba że sygnał SIGABRT zostanie przechwycony, a program obsługi sygnału nie powróci.
abort
wysyła SIGABRT
sygnał. abort
nie wraca do dzwoniącego. Domyślna obsługa SIGABRT
sygnału zamyka aplikację. stdio
strumienie plików są opróżniane, a następnie zamykane. Destruktory dla instancji klas C ++ nie są jednak (nie jesteś pewien tego - być może wyniki są nieokreślone?).
exit
ma własne wywołania zwrotne, ustawiane za pomocą atexit
. Jeśli podano wywołania zwrotne (lub tylko jeden), są one wywoływane w kolejności odwrotnej do ich kolejności rejestracji (jak stos), a następnie program kończy działanie. Podobnie jak w przypadku abort
, exit
nie wraca do dzwoniącego. stdio
strumienie plików są opróżniane, a następnie zamykane. Wywoływane są również destruktory dla instancji klas C ++.