En C et C++, quelle est la différence entre exit()
et abort()
? J'essaye de finir mon programme après une erreur (pas une exception).Quelle est la différence entre exit() et abort()?
Répondre
abort envoie un signal de SIGABRT, sortie ferme seulement l'application d'effectuer le nettoyage normal.
Vous pouvez gérer un abandonner le signal comme vous le souhaitez, mais le comportement par défaut est de fermer l'application avec un code d'erreur.
abort n'exécutera pas la destruction d'objets de vos membres statiques et mondiaux, mais sortie volonté.
Bien sûr, lorsque l'application est complètement fermée, le système d'exploitation libère toute mémoire non-programmée et d'autres ressources.
Dans les deux abort et sortie la fin du programme (en supposant que vous n'avez pas modifié le comportement par défaut), le code de retour sera retourné au processus parent qui a commencé votre application.
Voir l'exemple suivant:
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;
}
Commentaires:
Si abort est décommentée: rien est imprimé et le destructeur de SomeObject ne sera pas appelé.
Si abort est commenté comme ci-dessus: SomeObject destructor seront appelés, vous obtiendrez la sortie suivante:
fonction de sortie 2
fonction de sortie 1
abort()
quitte votre programme sans appeler les fonctions enregistrées en utilisant d'abord atexit()
, et sans appeler les objets de structeurs en premier. exit()
fait les deux avant de quitter votre programme. Il n'appelle pas les destructeurs pour les objets automatiques. Alors
A a;
void test() {
static A b;
A c;
exit(0);
}
aura-t-destruct a
et b
correctement, mais ne sera pas appeler de c
Destructeurs. abort()
n'appelait pas les destructeurs de deux objets. Comme cela est regrettable, la norme C++ décrit un autre mécanisme qui assure correctement la terminaison:
objets avec une durée de stockage automatique sont tous détruits dans un programme dont la fonction
main()
ne contient aucun objet automatique et exécute l'appel àexit()
. Le contrôle peut être transféré directement à un telmain()
en lançant une exception qui est interceptée dansmain()
.
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);
}
}
Au lieu d'appeler exit()
, en sorte que le code throw exit_exception(exit_code);
à la place.
+1 parce que, tandis que Brian R.Bondy était bon, vous avez soulevé le problème d'abandon/sortie (pas de destructeur d'objets de pile appelés), et vous avez offert l'alternative pour un processus C++ intensif RAII. – paercebal
Je cherchais un moyen de quitter un programme sans appeler dtor et votre réponse est exactement ce que je cherchais! Merci – acemtp
Cela est parfaitement correct bien sûr, si cela importe réellement que vos destructeurs d'objets automatiques ne sont pas appelés :-) –
abort
envoie le signal SIGABRT
. abort
ne revient pas à l'appelant. Le gestionnaire par défaut pour le signal SIGABRT
ferme l'application. stdio
Les flux de fichiers sont vidés, puis fermés. Les destructeurs pour les instances de classe C++ ne sont pas, cependant (pas sûr sur celui-ci - peut-être que les résultats sont indéfinis?).
exit
a ses propres rappels, définis avec atexit
. Si les rappels sont spécifiés (ou un seul), ils sont appelés dans l'ordre inverse de leur ordre d'enregistrement (comme une pile), puis le programme se termine. Comme avec abort
, exit
ne retourne pas à l'appelant. stdio
Les flux de fichiers sont vidés, puis fermés. En outre, les destructeurs pour les instances de classe C++ sont appelés.
exit peut avoir plusieurs fonctions de rappel enregistrées via atexit, lorsque exit est appelé, toutes les fonctions de rappel seront appelées dans l'ordre inverse dans lequel elles ont été enregistrées. –
@Gamble, Bien sûr, je l'ai mentionné moi-même il y a quelques minutes dans un commentaire à la réponse @ Bondy. Je vais modifier ma propre réponse pour refléter cela. – strager
De la sortie() dans le manuel:
La fonction exit() provoque la fin du processus normal et la valeur de statut & 0377 est renvoyé au parent.
De l'abort() Manuel:
Le abort() premier le signal débloque SIGABRT et soulève alors que le signal pour le processus d'appel. Cela entraîne la fin anormale du processus, sauf si le signal SIGABRT est intercepté et que le gestionnaire de signal ne revient pas.
Les choses suivantes se produisent lorsqu'un programme appelle exit
():
- Fonctions enregistrées par la fonction
atexit
sont exécutées - Tous les flux ouverts sont vidés et fermés, les fichiers créés par
tmpfile
sont supprimés - Le programme se termine avec le code de sortie spécifié à l'hôte
La fonction abort
() envoie le signal SIGABRT
au processus en cours, s'il n'est pas intercepté, le programme se termine sans garantie que les flux ouverts sont vidés/fermés ou que les fichiers temporaires créés via tmpfile
sont supprimés, atexit
les fonctions enregistrées ne sont pas appelées et un statut de sortie différent de zéro est renvoyé à l'hôte.
hmm. la norme dit que le programme n'est pas terminé si le gestionnaire de signal "ne retourne pas". vous êtes plutôt bien avec C. pouvez-vous imaginer un scénario qui permettrait de continuer l'exécution normale sans retour? J'imagine longjmp, mais je ne suis pas sûr de la façon dont il se comporte dans les gestionnaires de signaux. –
En général, appeler longjmp depuis un gestionnaire de signal est indéfini, mais il y a un cas spécial où le signal a été généré avec raise/abort, donc je suppose que cela serait théoriquement possible bien que je ne pense pas l'avoir déjà fait. Maintenant, je vais devoir essayer;) –
Cela semble fonctionner (cassé en plusieurs postes en raison de 300 limites char): #include
Ici, il a appelé la fonction de sortie 2 PUIS quitter la fonction 1. gcc 4, Linux 2.6. – strager
La page de manuel pour atexit dit: "Les fonctions [enregistrées en utilisant atexit] sont appelées dans l'ordre inverse, aucun argument n'est passé." – strager
@strager a raison, les fonctions enregistrées par atexit sont supposées être appelées dans l'ordre inverse lors de l'appel de exit ou des retours principaux. –