Quelle est la différence entre ces trois options et comment dois-je terminer le programme en cas d'exception que je ne peux pas gérer correctement?
Réponses
Trop de publicités?Mon conseil serait de ne pas en utiliser. Au lieu de cela, attraper
les exceptions que vous ne pouvez pas gérer dans main()
et simplement retourner
à partir de là. Cela signifie que vous avez la garantie que le déroulement de la pile se fait correctement et que tous les destructeurs sont appelés. En d'autres termes:
int main() {
try {
// vos choses
}
catch( ... ) {
return 1; // ou autre chose
}
}
Cette réponse contient beaucoup d'informations utiles et correctes sur les fonctions de la question originale, mais si l'exception ne peut pas être gérée correctement comme le suggère l'OP, cela pourrait être un rapport de bug erroné comme std::logic_error
, et dans ce cas, le conseil de laisser l'exception se propager pourrait ne pas être idéal. Il est possible que l'OP sache qu'il a une condition irrécupérable telle qu'un bug qui nécessite la fermeture du programme.
Lorsqu'un bug est détecté, le programme ne peut pas continuer de manière fiable, et lancer une exception risque de détruire des informations de débogage précieuses dont vous avez besoin pour trouver le bug, laisser un état corrompu, ouvrir une faille de sécurité et cacher le bug aux développeurs. Lorsqu'un bug est détecté, vous voulez que le code minimal nécessaire s'exécute, peut-être quelques mesures de fermeture d'urgence soigneusement sélectionnées, avant de quitter et vous voulez capturer autant d'informations que possible sur l'état du programme dans le rapport de crash ou le vidage mémoire.
Lancer une exception est pour des conditions dont la source exacte peut être prévue à l'avance et qui a donc une procédure de récupération fiable, comme manquer d'espace disque lors de la sauvegarde d'un fichier ou trouver une entrée utilisateur incorrecte lors de l'analyse. (Vous voulez également savoir que l'erreur n'est probablement pas gérée dans l'appelant immédiat, et qu'elle ne se produit pas assez souvent sur le chemin critique pour nuire aux performances). Ce n'est pas pour des situations qui exigent la fermeture du programme.
Le principal outil que nous avons pour quitter en cas de bug s'appelle assert
. Malheureusement, une assertion échouée vous envoie directement à abort
, donc il n'y a pas de chance de prendre des mesures de fermeture d'urgence que vous pourriez mettre dans un gestionnaire terminate
- mais vous n'en avez peut-être pas besoin, et abort
est toujours préférable au lancer d'exception. assert
n'offre pas non plus un contrôle assez fin sur quand la vérification sera effectuée (debug/release?) ni ne capture suffisamment d'informations sur la raison de la vérification (s'agit-il d'une vérification de précondition ou d'une vérification de cohérence, ou autre chose?). Bien faire la détection de bugs avec sortie nécessite un ensemble de remplacements de assert
qui permettent de contrôler quand ils sont en vigueur et capturer des sémantiques, et d'appeler terminate()
en cas d'échec. Si vous ne pouvez pas gérer cela, utilisez assert
pour la détection de bugs.
Même s'il ne s'agit pas d'un bug, si vous deviez quitter, lancer une exception tentera le code plus haut dans la pile de continuer.
- Réponses précédentes
- Plus de réponses
3 votes
Ce n'est pas un doublon, mais plutôt un sous-ensemble avec quelques bonnes réponses stackoverflow.com/questions/397075/… et il était aussi marqué C++!
0 votes
std::abort
est raisonnable si une exception ne peut pas être résolue dans un destructeur.1 votes
Pour plus d'informations sur
std::terminate
, consultez ces articles du blog C++ excellent d'Andrzej : akrzemi1.wordpress.com/2011/09/28/who-calls-stdterminate , akrzemi1.wordpress.com/2011/10/05/using-stdterminate