Confus à propos de std :: runtime_error vs. std :: logic_error

J’ai récemment vu que la bibliothèque boost logic_error lève un logic_error si l’entrée de ligne de commande était non analysable. Cela remettait en cause mes hypothèses à propos de logic_error vs. runtime_error .

J’ai supposé que les erreurs logiques ( logic_error et ses classes dérivées) étaient des problèmes résultant de défaillances internes d’adhésion aux invariants de programme, souvent sous la forme d’arguments illégaux aux API internes. En ce sens, ils sont largement équivalents à ASSERT, mais destinés à être utilisés dans le code publié (contrairement à ASSERT qui ne sont généralement pas compilés dans le code publié). Ils sont utiles dans des situations où l’intégration de composants logiciels distincts est impossible ou les conséquences d’une défaillance sont telles qu’il est important de donner à l’utilisateur un retour à l’exécution sur la condition d’invariance invalide.

De même, je pensais que runtime_error s résultait exclusivement de conditions d’exécution en dehors du contrôle du programmeur: erreurs d’E / S, entrées d’utilisateur non valides, etc.

Cependant, program_options est évidemment utilisé principalement (principalement?) Comme moyen d’parsingr les entrées de l’utilisateur final, donc sous mon modèle mental, il devrait certainement lancer une runtime_error en cas de mauvaise saisie.

Où est-ce que je me trompe? Êtes-vous d’accord avec le modèle de boost du typage des exceptions?

Dans ce cas, je pense (du moins pour la plupart) que vous avez raison et que c’est faux. La norme décrit logic_error comme logic_error :

La classe logic_error définit le type d’objects renvoyés en tant qu’exceptions pour signaler les erreurs probablement détectables avant l’exécution du programme, telles que les violations des conditions préalables logiques ou des invariants de classe.

Un argument de ligne de commande qui ne peut pas être analysé ne semble pas très bien adapté.

En revanche, runtime_error décrit comme runtime_error :

La classe runtime_error définit le type d’objects renvoyés en tant qu’exceptions pour signaler les erreurs probablement détectables uniquement lorsque le programme est exécuté.

Cela semble être un meilleur ajustement.

D’un sharepoint vue purement standard, vous avez raison. program_options devrait lancer des classes dérivées de runtime_error ou logic_error selon que l’erreur est à l’exécution ou logique. (Je n’ai pas examiné le code actuel pour déterminer une telle classification d’idées pour les exceptions actuelles).

D’un sharepoint vue pratique, je n’ai pas encore vu de code C ++ qui prenne des décisions utiles selon que l’exception est logic_error ou runtime_error . Après tout, la seule raison pour laquelle vous logic_error un logic_error au lieu de laisser assert le fichier, c’est si vous voulez essayer de récupérer en quelque sorte, et ce n’est pas différent de la récupération après une erreur d’exécution. Personnellement, je logic_error vs. runtime_error la même manière que les exceptions vérifiées dans Java – théoriquement bien, mais pas utile dans la pratique. Ce qui signifie que peut-être, je ferai simplement que program_options::error dérive de l’ exception . C’est-à-dire que je trouverai ce «temps libre» dont tout le monde parle.

Le brouillon actuel de la norme C ++ 0x indique (clause 19.2):

1) Dans le modèle d’erreur reflété dans ces classes (c.-à-d. Les types d’exception), les erreurs sont divisées en deux grandes catégories: les erreurs logiques et les erreurs d’exécution.

2) La caractéristique distinctive des erreurs logiques est qu’elles sont dues à des erreurs dans la logique interne du programme. En théorie, ils sont évitables.

3) En revanche, les erreurs d’exécution sont dues à des événements dépassant le cadre du programme. Ils ne peuvent pas être facilement prédits à l’avance.

Avec les citations citées dans l’une des autres réponses, cela explique pourquoi Boost.ProgramOptions émet un std :: logic_error pour les erreurs évitables causées par une “erreur présumée détectable avant l’exécution du programme”.

L’utilisateur peut vérifier que le fichier existe, exécuter le programme et apprendre soudainement que le fichier a été supprimé. C’est pourquoi un problème d’E / S est toujours une runtime_error . Les problèmes d’état sont des runtime_errors, même si l’appelant aurait pu vérifier, car un autre thread pouvait causer le problème.

logic_error est le moment où les arguments d’une fonction sont erronés. Ce n’est que pour les choses qui auraient pu être sockets plus tôt avec une vérification de type plus forte.

Ainsi, “fichier manquant” est une runtime_error , mais “nom de fichier incorrectement formaté” est une logic_error .

Techniquement, une erreur logique dans une fonction est également une erreur de logique, mais si vous êtes assez intelligent pour le tester dans votre propre fonction, vous devriez être suffisamment intelligent pour l’empêcher en premier lieu.

OMI,

  • std::logic_error est lancé intentionnellement par une logique de programme utilisateur C ++. Prévu par un programme utilisateur.

  • std::runtime_error est lancé par un std::runtime_error exécution C ++ (ou partie principale de la langue…) pour abstraire les erreurs de niveau inférieur. Cela se passe sans aucune intention sans impliquer de code utilisateur.