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 ai bpoprawnie, 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 SIGABRTsygnał 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ą tmpfilezostaną usunięte, atexitzarejestrowane 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.
abortwysyła SIGABRTsygnał. abortnie wraca do dzwoniącego. Domyślna obsługa SIGABRTsygnału zamyka aplikację. stdiostrumienie 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?).
exitma 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, exitnie wraca do dzwoniącego. stdiostrumienie plików są opróżniane, a następnie zamykane. Wywoływane są również destruktory dla instancji klas C ++.