std::exit
| Défini dans l'en-tête <cstdlib>
|
||
void exit( int exit_code );
|
(jusqu'à C++11) | |
[[noreturn]] void exit( int exit_code );
|
(depuis C++11) | |
Provoque une terminaison normale du programme.
Plusieurs étapes de nettoyage sont effectuées :
|
1) Les objets à durée de stockage statique sont détruits et les fonctions enregistrées en appelant std::atexit sont appelées :
a) Les objets non locaux à durée de stockage statique sont détruits dans l'ordre inverse de l'achèvement de leur constructeur.
b) Les fonctions enregistrées avec std::atexit sont appelées dans l'ordre inverse de leur enregistrement, sauf qu'une fonction est appelée après toutes les fonctions précédemment enregistrées qui avaient déjà été appelées au moment de son enregistrement.
c) Pour chaque fonction
f enregistrée avec std::atexit et chaque objet non local obj à durée de stockage statique,
d) Pour chaque objet local obj à durée de stockage statique, obj est détruit comme si une fonction appelant le destructeur de obj était enregistrée avec std::atexit à l'achèvement du constructeur de obj.
|
(jusqu'à C++11) |
|
1) Les destructeurs des objets à durée de stockage thread local associés au thread courant, les destructeurs des objets à durée de stockage statique, et les fonctions enregistrées avec std::atexit sont exécutés simultanément, tout en maintenant les garanties suivantes :
a) Le dernier destructeur pour les objets thread-locaux est séquence-avant le premier destructeur pour un objet statique.
b) Si l'achèvement du constructeur ou l'initialisation dynamique pour un objet thread-local ou statique A était séquence-avant l'objet thread-local ou statique B, l'achèvement de la destruction de B est séquence-avant le début de la destruction de A.
c) Si l'achèvement de l'initialisation d'un objet statique A était séquence-avant l'appel à std::atexit pour une fonction F, l'appel à F pendant la terminaison est séquence-avant le début de la destruction de A.
d) Si l'appel à std::atexit pour une fonction F était séquence-avant l'achèvement de l'initialisation d'un objet statique A, le début de la destruction de A est séquence-avant l'appel à F pendant la terminaison.
e) Si un appel à std::atexit pour une fonction F1 était séquence-avant l'appel à std::atexit pour une fonction F2, alors l'appel à F2 pendant la terminaison est séquence-avant l'appel à F1.
|
(depuis C++11) |
- Dans ce qui précède,
- Si une fonction enregistrée avec
atexitou tout destructeur d'objet statique/thread-local lève une exception, std::terminate est appelé. - Si le compilateur a choisi de reporter l'initialisation dynamique d'un objet à la phase d'initialisation statique de l'initialisation non locale, l'ordonnancement de la destruction honore son initialisation dynamique potentielle.
- Si un objet statique local à une fonction (de portée de bloc) a été détruit et que cette fonction est ensuite appelée depuis le destructeur d'un autre objet statique et que le flux de contrôle passe par la définition de cet objet (ou s'il est utilisé indirectement, via un pointeur ou une référence), le comportement est indéfini.
- Si un objet statique local à une fonction (de portée de bloc) a été initialisé lors de la construction d'un sous-objet d'une classe ou d'un tableau, il n'est détruit qu'après que tous les sous-objets de cette classe ou tous les éléments de ce tableau ont été détruits.
- Si une fonction enregistrée avec
exit_code est 0 ou EXIT_SUCCESS, un statut défini par l'implémentation indiquant une terminaison réussie est renvoyé. Si exit_code est EXIT_FAILURE, un statut défini par l'implémentation indiquant une terminaison échouée est renvoyé. Dans les autres cas, une valeur de statut définie par l'implémentation est renvoyée.La pile n'est pas déroulée : les destructeurs des variables à durée de stockage automatique ne sont pas appelés.
Relation avec la fonction main
Le retour de la
fonction main
, soit par une instruction
return
soit en atteignant la fin de la fonction, effectue la terminaison normale de la fonction (appelle les destructeurs des variables avec
durée de stockage automatique
) puis exécute
std::exit
, en passant l'argument de l'instruction return (ou
0
si un retour implicite était utilisé) comme
exit_code
.
Paramètres
| exit_code | - | statut de sortie du programme |
Exemple
#include <cstdlib> #include <iostream> struct Static { ~Static() { std::cout << "Static destructor\n"; } }; struct Local { ~Local() { std::cout << "Local destructor\n"; } }; Static static_variable; // Le destructeur de cet objet *sera* appelé void atexit_handler() { std::cout << "atexit handler\n"; } int main() { Local local_variable; // Le destructeur de cet objet *ne sera pas* appelé const int result = std::atexit(atexit_handler); // Le gestionnaire sera appelé if (result != 0) { std::cerr << "atexit registration failed\n"; return EXIT_FAILURE; } std::cout << "test\n"; std::exit(EXIT_FAILURE); std::cout << "this line will *not* be executed\n"; }
Sortie :
test atexit handler Static destructor
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Appliqué à | Comportement tel que publié | Comportement corrigé |
|---|---|---|---|
| LWG 3 | C++98 |
pendant le nettoyage, le comportement n'était pas clair quand (1) une fonction est
enregistrée avec std::atexit ou (2) un objet local statique est initialisé |
clarifié |
Voir aussi
|
provoque la fin anormale du programme (sans nettoyage)
(fonction) |
|
|
enregistre une fonction à appeler lors de l'invocation de
std::exit()
(fonction) |
|
|
(C++11)
|
provoque la fin rapide du programme sans nettoyage complet
(fonction) |
|
(C++11)
|
enregistre une fonction à appeler lors de l'invocation de
std::quick_exit
(fonction) |
|
Documentation C
pour
exit
|
|