2008-12-29 10 views

Répondre

29

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

+0

Ici, il a appelé la fonction de sortie 2 PUIS quitter la fonction 1. gcc 4, Linux 2.6. – strager

+1

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

+0

@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. –

106

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 tel main() en lançant une exception qui est interceptée dans main().

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

+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

+0

Je cherchais un moyen de quitter un programme sans appeler dtor et votre réponse est exactement ce que je cherchais! Merci – acemtp

+0

Cela est parfaitement correct bien sûr, si cela importe réellement que vos destructeurs d'objets automatiques ne sont pas appelés :-) –

4

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.

+0

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. –

+0

@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

5

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.

10

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.

+0

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. –

+0

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;) –

+1

Cela semble fonctionner (cassé en plusieurs postes en raison de 300 limites char): #include #include #include #include de do_abort de sig_atomic_t volatile = 1; jmp_buf env; void abort_handler (int i) {do_abort = 0; longjmp (env, 1); –

Questions connexes