pourquoi faut-il bannir std::exit | bloc try-catch fonctionnel - C++ - Programmation
Marsh Posté le 07-09-2003 à 22:32:21
ah, cool j'avais dejà un peu pensé à un truc comme ca, vu mon niveau chui fier de moi
Marsh Posté le 07-09-2003 à 22:36:11
BlackGoddess a écrit : ah, cool j'avais dejà un peu pensé à un truc comme ca, vu mon niveau chui fier de moi |
merde, t'es un mec
Marsh Posté le 07-09-2003 à 22:38:05
oui, il est vrai que mon pseudo peut prêter a confusion ...
Marsh Posté le 07-09-2003 à 22:48:51
BlackGoddess a écrit : oui, il est vrai que mon pseudo peut prêter a confusion ... |
dommage pour toi, maintenant on ne te repondra plus
Marsh Posté le 08-09-2003 à 09:27:31
muh
si j'avais su j'aurais écrit fière
Marsh Posté le 08-09-2003 à 10:03:32
sauf quand tu programmes des drivers.
Mais bon faire exit() c'est pas une bonne idée dans ce cas la non plus .
LeGreg
Marsh Posté le 20-10-2004 à 23:10:29
Est-ce qu'un segfault déclenche catch(...) ?
Marsh Posté le 20-10-2004 à 23:34:16
non, un segfault, c'est un signal venant du noyau. En cas de segfault, le mieux est de ne rien faire. Si ça segfault, c'est que tu as corrompu ton espace mémoire : aucune contrainte n'est plus assurée, tu ne peux rien faire avec certitude. Alors autant arrêter les dégats.
Marsh Posté le 20-10-2004 à 23:42:15
Effectivement, on peut rediriger le signal segfault mais l'execution est compromise.
Lorsque plusieurs bloques try-catch sont encapsulé, tu conseilles de manière générale de relancer le gestionnaire d'exception avec un throw dans les blocks catch ? ... histoire de retourner jusque dans le block catch de plus haut niveau, celui du main().
Marsh Posté le 20-10-2004 à 23:46:50
Taz a écrit : non, un segfault, c'est un signal venant du noyau. En cas de segfault, le mieux est de ne rien faire. Si ça segfault, c'est que tu as corrompu ton espace mémoire : aucune contrainte n'est plus assurée, tu ne peux rien faire avec certitude. Alors autant arrêter les dégats. |
Si je redirige le signal correspondant au segfault vers une simple routine qui appel throw. Est-ce le block catch de la fonction en cours d'execution va s'executer ? Je sais, c'est tordu...
Marsh Posté le 20-10-2004 à 23:47:19
je comprends pas ta question. Si tu fais un catch, ne catch que ce que tu sais traiter. Tu peux également avoir des catch qui lance une nouvelle exception afin de préciser celle-ci (ou de lui donner un sens dans le contexte appelant).
Marsh Posté le 20-10-2004 à 23:51:06
En somme ma question etait, est ce qu'on peut généraliser ton conseil (un double bloque try-catch dans le main) à toutes les fonctions et fonctions membres ? Y compris lorsqu'on ne sait pas traiter l'exception (tanpis, cela permet qd meme de la localiser finement).
Marsh Posté le 21-10-2004 à 00:05:20
ben non. Ça te sert à quoi d'attraper des exceptions dont tu n'a rien à faire ?
Marsh Posté le 21-10-2004 à 00:19:39
A peu de chose. Principalement à la localiser.
Marsh Posté le 21-10-2004 à 00:26:57
Ce n'est pas comme ça qu'il faudrait faire. y a pas de mécanisme de stacktrace en C++. tu veux t'aider avec __FILE__ et ses potes. La vrai question toute façon, c'est à quoi sert de localiser précisément une exception, à part afficher un message bien imbittable à l'utilisateur (n'est-ce pas Java ?). Si tu peux traiter une exception, attrape là, et résous le problème si. Sinon, ne fais rien. Souviens toi que le code que tu manipules peux lancer n'importe quoi (surtout avec les templates). Ne présume de rien.
Marsh Posté le 21-10-2004 à 12:23:12
Bon, déjà, Sous Windows, un segfault lance une exception rattrapable avec catch (...)
D'autre part, les stack-traces, c'est vraiment très très pratique lorsque tu as des merdes sur un projet énorme à l'autre bout du monde et qui tourne depuis des jours: ça te permet de voir où ça merde, éventuellement pourquoi, sans avoir à retrouver la combinaison qui l'a fait planter.
Bref, dans ma boite on avait carrément implémenté le méchanisme permettant de les récupérer (soit on récupère le signal, et on exécute pstack sur le programme, soit on rajoute des infos de contexte qui créent une stack-trace virtuelle).
Et l'utilisateur, il est content, parce qu'il n'a pas besoin d'écrire sur un bout de papier tout ce qu'il fait pour déclencher le crash, et parce qu'il a son diagnostic plus rapidement...
Marsh Posté le 07-09-2003 à 16:16:28
pré-requis :
- connaître le mécanisme des exceptions
- savoir comment créer ses propres exceptions
- savoir attraper sainement une exception
Je crois que j'en avais déjà parlé, mais je le formalise: pourquoi ne faut-il jamais, je dis bien jamais, utiliser std::exit (et les autres fonctions de sa famille). Une première bonne raison à mes yeux: elle vient du C, donc par définition, on va avoir des problèmes avec. Souvent quand on conçoit un programme, le traitement d'erreur implique des erreurs fatales (arrêt du programme), que l'on gère ça bien par exceptions, ou bien comme un cochon avec des codes d'erreurs ("Failure is not an error" d'ailleurs, si vous voulez une petite discussion sur les exceptions -> http://forum.hardware.fr/forum2.ph [...] 499&cat=10 , devenez adepte de la méthode EAFP fin de la ). Donc cette erreur fatale, vous la matérialisez par un appel à std::exit(). Malheureusement, c'est le coup de grâce. std::exit est une fonction bête qui va tuer votre programme d'un coup. Vous programmez bien avec une foultitude d'objets, bien, mais std::exit sans fiche bien, vos destructeurs ne seront __jamais__ appelés ... c'est vraiment un arrêt brutal, imaginez les conséquences si vous devez absolument relâcher certaines ressources (fichiers, verrous, connexions réseaux, matériel ...). l'horreur !
Heureusement la solution est très simple dans le cas où cette erreur est inextrippable (impossible de retourner dans le main pour faire un joli return), il vous suffit de balancer une exception et de l'attendre. J'insiste bien sur le point « attendre » car le gestionnaire d'exceptions inattendues par défaut fera un appel à un truc genre _abort dont l'effet est le même que std::exit.
Donc enserrer votre main dans un joli bloc try et placer 2 bloc catch: le premier pour std::exception, c'est à dire pour ramasser tout ce que vous lancer (intentionnellement ou pas) et un deuxième catch(...) pour rammasser le reste. Le mécanisme des exceptions assurant la destruction des objets, nous voilà hors de danger, tout est propre et sur, les erreurs sont maitrisées.
Notez une synthaxe un peu inhabituelle dans l'exemple: le bloc try fonctionnel, c'est à dire pour enserrer une fonction (ou bien un constructeur, c'est là une autre discussion). c'est juste un exemple, je ferais sans doute un article sur cette construction, sachez qu'elle existe.
c++ exit.cpp -> gestion avec std::exit
c++ -DHFR_EXCEPTION exit.cpp -> gestion avec exception
comptez bien les instances zombies
remarquez que cette méthode (enchasser le main avec 1 try / 2 catch) est la marque de bons logiciels.
Message édité par Taz le 21-10-2004 à 11:29:55