226 votes

instruction return vs exit() dans main()

Dois-je utiliser exit() ou simplement return les déclarations dans main() ? Personnellement, je privilégie le return car j'ai l'impression que c'est comme lire n'importe quelle autre fonction et que le contrôle du flux lorsque je lis le code est fluide (à mon avis). Et même si je veux refactoriser le code main() fonction, ayant return semble être un meilleur choix que exit() .

Fait exit() faire quelque chose de spécial qui return ne le fait pas ?

309voto

FreeMemory Points 4742

En fait, il y a est une différence, mais elle est subtile. Cela a plus d'implications pour le C++, mais les différences sont importantes.

Quand j'appelle return en main() Les destructeurs seront appelés pour mes objets à portée locale. Si j'appelle exit() , aucun destructeur ne sera appelé pour mes objets à portée locale ! Relis ça. exit() ne renvoie pas . Cela signifie qu'une fois que je l'ai appelée, il n'y a "pas de retour en arrière". Tous les objets que vous avez créés dans cette fonction ne seront pas détruits. Souvent, cela n'a pas d'implications, mais parfois, cela en a, comme la fermeture de fichiers (vous voulez sûrement que toutes vos données soient effacées sur le disque).

Notez que static seront nettoyés même si vous appelez exit() . Enfin, notez que si vous utilisez abort() aucun objet ne sera détruit. C'est-à-dire qu'aucun objet global, aucun objet statique et aucun objet local ne verra son destructeur appelé.

Faites preuve de prudence lorsque vous privilégiez la sortie par rapport au retour.

http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a

2 votes

Abort() sort avec une condition d'erreur (code de sortie non nul) et peut même être un noyau. Si vous avez besoin de sortir sans appeler les destructeurs statiques, utilisez _exit .

0 votes

@Arkadiy Absolument. abort signale une condition d'erreur. Et, d'un point de vue stylistique, j'utilise généralement exit() pour signaler une condition d'erreur, et je retourne 0 depuis main pour indiquer une terminaison normale.

1 votes

Extrait de la page de manuel exit() : 2. Vider tous les flux de sortie ouverts. Il semble que tous les flux de sortie ouverts seraient vidés, que le destructeur approprié soit appelé ou non.

30voto

jwfearn Points 8813

Une autre différence : exit est une bibliothèque standard donc vous devez inclure et lier avec la bibliothèque standard standard. Pour illustrer (en C++), ceci est un programme valide :

int main() { return 0; }

mais pour utiliser exit vous aurez besoin d'un include :

#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }

En outre, cela ajoute une hypothèse supplémentaire : que l'appel exit de main a les mêmes effets secondaires que le retour de zéro. Comme d'autres l'ont fait remarquer, cela dépend du type d'exécutable que vous construisez (c'est-à-dire qui appelle main ). Est-ce que vous codez une application qui utilise le C-runtime ? Un plugin Maya ? Un service Windows ? Un pilote ? Chaque cas nécessitera une recherche pour voir si exit est équivalent à return . IMHO utiliser exit quand vous vraiment méchant return rend juste le code plus confus. Par contre, si vous veulent vraiment dire exit alors il faut l'utiliser.

0 votes

L'ISO C garantit que ce qui se passe lorsque main revient est équivalent à ce que l'appelant de main passe la valeur de retour à l'adresse suivante exit() . Retour et sortie de la fonction principale en C a des réponses qui citent la norme. Si votre programme n'est pas exécuté en tant que processus autonome, la première fonction ne s'appelle probablement pas main . Si c'est le cas, vous faites du vaudou bizarre et vous n'êtes plus au pays de l'ISO C.

17voto

R.. Points 93718

Il y a au moins une raison de préférer exit : Si l'un de vos atexit se réfèrent à des données de durée de stockage automatique en main ou si vous avez utilisé setvbuf o setbuf pour attribuer à l'un des flux standard un tampon à durée de stockage automatique en main puis en revenant de main produit un comportement indéfini, mais appeler exit est valable.

Une autre utilisation potentielle (généralement réservée aux programmes jouets, cependant) est de sortir d'un programme avec des invocations récursives de main .

0 votes

C'est intéressant, car [en C, au moins] 5.1.2.2.3p1 déclare que return 0; depuis l'appel initial à main est équivalent à exit(0); ... Est-il possible que ce soit un bug du compilateur (ou un fonction du compilateur selon la personne à qui vous demandez) ?

1 votes

@Seb il n'y a rien de spécial à propos de main() -- c'est juste une fonction comme une autre. D'un autre côté, puisqu'elle a une mention spéciale dans la norme, la norme doit être assez prudente sur la façon dont elle définit main() et les choses qui lui sont proches. Cependant, en fin de compte, la norme ne fait pas (et ne fait pas ne doit pas ) exigent que les compilateurs fassent quelque chose de spécial à propos du stockage automatique dans les fichiers main() . Veuillez prendre soin de lire Note de bas de page n° 11 sous le paragraphe auquel vous faites référence dans votre commentaire.

1 votes

@GregA.Woods Intéressant. Il semble qu'il y ait un texte normatif en contradiction avec un texte informatif. Selon les directives ISO/CEI La référence normative est considérée comme "indispensable", alors que la référence informative n'est considérée que comme complémentaire... En outre, l'utilisation du mot "will" pour exprimer une exigence n'est pas valable, selon le document susmentionné (annexe H). En résumé, le texte informatif est très certainement invalide.

5voto

Alnitak Points 143355

J'utilise toujours return car le prototype standard de main() dit qu'il renvoie bien un int .

Cela dit, certaines versions des normes donnent main traitement spécial et supposer qu'il retourne 0 s'il n'y a pas d'explicite return déclaration. Étant donné le code suivant :

int foo() {}
int main(int argc, char *argv[]) {}

G++ ne génère un avertissement que pour foo() et ignore le retour manquant de main :

% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo()’:
foo.cc:1: warning: control reaches end of non-void function

0 votes

Je ne sais pas pour le C, mais le standard C++ spécifie que si vous ne retournez pas une valeur dans main, il est supposé retourner 0.

0 votes

Il semble que le C99 soit le même : faq.cprogramming.com/cgi-bin/

3 votes

C99 et C++ renvoient 0 s'il n'y a pas de déclaration de retour, C90 ne le fait pas.

5voto

Greg A. Woods Points 683

I FORTEMENT seconder le commentaire de R. concernant l'utilisation de exit() pour éviter d'avoir un stockage automatique dans l'espace de stockage de l'utilisateur. main() récupérés avant la fin effective du programme. A return X; déclaration dans main() n'est pas précisément équivalent à un appel à exit(X); puisque le stockage dynamique de main() disparaît lorsque main() retourne, mais il ne disparaît pas si un appel à exit() est faite à la place.

De plus, en C ou dans un langage similaire, une fonction return laisse fortement entendre au lecteur que l'exécution se poursuivra dans la fonction appelante, et bien que cette poursuite de l'exécution soit techniquement vraie si l'on compte la routine de démarrage C qui a appelé la fonction main() ce n'est pas exactement ce que vous quand vous voulez mettre fin au processus.

Après tout, si vous voulez terminer votre programme à partir de n'importe quelle fonction autre que main() vous doit llame a exit() . En le faisant de manière cohérente dans main() rend également votre code beaucoup plus lisible et permet à quiconque de le remanier plus facilement ; par exemple, le code copié à partir de main() à une autre fonction ne se comportera pas mal à cause d'un accident. return les déclarations qui debe ont été exit() appels.

Donc, en combinant tous ces points ensemble, la conclusion est que c'est un mauvaise habitude au moins pour C, d'utiliser un return pour terminer le programme en main() .

0 votes

Vous pourriez trouver 5.1.2.2.3p1 de la norme C intéressant...

1 votes

Cette réponse mérite d'être examinée attentivement pour les programmes C, comme l'indique le contexte dans la réponse. Pour une utilisation avec C++, elle doit être soigneusement évaluée en tenant compte de tous les avertissements mentionnés précédemment. Pour le C++, je suggère d'éviter exit() en général, mais utilisez-le si un throw o abort() Les alternatives ne fonctionnent pas dans un contexte spécifique. Mais évitez surtout exit() dans main, et d'utiliser return dans main à la place comme pratique typique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X