Comment gérer les exceptions dans un langage procédural comme C ou Perl? (Je sais que Perl fait aussi OO.) Quelle est la meilleure façon de gérer l'exception dans le code de procédure en Perl?Comment gérer les exceptions dans un langage procédural?
Répondre
Cela dépend plutôt de ce que vous entendez par «gestion des exceptions».
Certains systèmes d'exploitation ont des mécanismes d'exception - voir Windows exception handling routines ou Linux signal handlers (dont certains sont des exceptions). Si vous voulez dire l'idiome dans le code utilisateur pour signaler une erreur et dérouler la pile en nettoyant les objets alloués, alors le code C n'appelle pas les destructeurs sur les objets alloués quand la pile est déroulée (elle récupère juste la mémoire), il est donc normal en C que les fonctions retournent une valeur d'état, et que le code appelant fasse le nettoyage requis avant de retourner. Je ne connais pas bien Perl, mais Google pour "gestion des exceptions Perl" indique qu'il a à la fois des mécanismes intégrés équivalents à try/catch et des modules qui donnent une gestion des exceptions de type "OO".
L'approche traditionnelle est ... eh bien ... pas :)
En général, les gens se contentent de vérifier l'état après avoir essayé quelque chose, et si quelque chose a mal tourné, ils nettoient et retourner un code d'erreur, plutôt que de continuer. Cette erreur contrôle et de retour se propage vers le bas de la pile d'appel de fonction jusqu'à ce qu'il revienne à un endroit de haut niveau dans votre programme, où vous soin d'informer l'utilisateur au lieu de simplement revenir plus d'erreurs:
int try_it() {
if (!do_something(...)) {
return TRYIT_FAILURE;
}
}
void my_gui() {
rc = try_it()
if (rc == TRYIT_FAILURE) {
message_box("failed when trying it.", MB_ABORT|MB_RETRY);
}
...
}
Vous pouvez également faire cela dans une grande fonction, en utilisant ifs imbriqués, si vous voulez quelque chose comme un essai ... sauf construction:
if (stage1()) {
if (stage2()) {
if(stage3()) {
printf("success!\n");
} else {
// error handling for stage 3
}
} else {
// error handling for stage 2
}
} else {
// error handling for stage 1
}
Et vous pouvez faire la même chose avec GOTO si vous êtes un peu fou.
Cependant, vous pouvez faire des exceptions réelles, au moins en C. C a deux appels de bibliothèque standard pour ce genre de chose: setjmp et longjmp. Avec ceux-ci, vous pouvez revenir en arrière à travers plusieurs appels de fonction à un endroit prédéterminé, où vous savez que l'exception (saut) s'est produite. Voir Setjmp.h#exception_handling on wikipedia pour plus d'informations à ce sujet.
Il semble que Perl ait un moyen de le faire, même si cela me semble loin d'être intuitif. Là encore, je ne suis pas le code en Perl :)
-1 Les développeurs Perl utilisent très certainement des exceptions. Je dirais qu'ils sont plus importants dans un langage dynamique comme Perl que dans un langage comme Java ou C++; –
En C il y avait setjmp et longjump; Pour l'essentiel, setjmp() enregistre le contexte actuel dans la pile, et longjmp() peut revenir au point sauvegardé par setjmp(). L'entrée wikipedia sur ces remplit joliment les détails.
En Perl 5, la gestion des exceptions est effectuée en utilisant eval
et die
. Vous évaluez simplement le corps du code et s'il meurt, vous pouvez inspecter [email protected]
pour l'erreur. Ce n'est pas si simple si vous voulez le faire correctement, c'est pourquoi les différents modules try/catch existent. Vous pourriez être intéressé par Try::Tiny qui n'a pas de dépendances et décrit tous les pièges que vous avez à traiter lorsque vous utilisez la gestion des exceptions eval naïf. (Voir aussi this blog post par l'auteur de Try :: Tiny.)
"eval" a des pénalités de performance qui peuvent le rendre prohibitif pour les systèmes à grande échelle. – DVK
@DVK, parlez-vous de chaîne eval ou bloc eval? Les problèmes avec l'évaluation de chaîne sont bien connus, mais la gestion des exceptions avec eval utilise généralement l'évaluation de bloc. Si vous dites qu'il y a des problèmes de performance avec Block Eval, pouvez-vous fournir une source ou une démonstration du problème? – daotoad
Pour ce que ça vaut, http://gist.github.com/187483. – zoul
Voici un exemple de la façon dont je fais des exceptions en Perl (sans utiliser l'un des modules Try):
use Carp;
use English qw(-no_match_vars);
do_something_needing_rollback_if_failed();
eval {
do_something_dangerous();
} or do {
# Exception was thrown by dangerous method
# Save the error:
my $error = $EVAL_ERROR;
# Try to rollback
eval { rollback(); }
or do { confess qq{Couldn't rollback: $EVAL_ERROR. Original error $error}; }
# Let's rethrow:
confess qq{Rolled back! Error was $error};
}
L'une des parties les plus gênants de la gestion des exceptions Perl est-il utilise une seule variable pour stocker toute erreur d'exception, et il peut être accidentellement écrasé, donc un codage défensif est requis.
En Perl, comme d'habitude, il y a plusieurs façons de le faire. Cependant, la communauté des développeurs a dans l'ensemble choisi la bonne façon de faire la plupart des choses.
Je suis de plus en plus fan de Exception::Base.
Si vous souhaitez une implémentation plus légère, utilisez simplement Carp.
Vous piègez des exceptions à l'aide d'une construction eval { ... }; if ([email protected]) { ... }
.
Avec Exception :: Base, il offre un moyen d'extraire la construction if ([email protected]) { ... }
pour vous. Cependant, vous devrez toujours utiliser eval { ... }
.
- 1. comment gérer les exceptions dans DLL C# chargées par C++
- 2. Comment gérer les exceptions générales dans Asp.Net MVC?
- 3. C# windows-services - Comment gérer les exceptions de journalisation?
- 4. Fonction de hachage procédural
- 5. conception pour gérer les exceptions - google app engine
- 6. Comment gérer les exceptions pendant un cycle de vie de demande ASP.NET
- 7. Quelle est la meilleure façon de gérer les exceptions ObjectDataSource?
- 8. Quelle est la meilleure approche pour gérer les exceptions lancées dans un thread séparé?
- 9. Est-il possible de gérer les exceptions dans les requêtes LINQ?
- 10. Comment puis-je gérer les exceptions dans une compréhension de liste en Python?
- 11. code simple pour gérer JNI exceptions
- 12. Java Gestion des exceptions dans les "événements"
- 13. Quelle est la meilleure pratique pour gérer toutes les exceptions dans l'application WPF?
- 14. Comment gérer les exceptions lors de l'utilisation du thread et de la file d'attente?
- 15. Comment gérer les valeurs incorrectes dans un constructeur?
- 16. Comment gérer les caractères spéciaux dans un Java PrepareStatement?
- 17. Ruby: contexte indésirable dans les exceptions soulevées dans un eval
- 18. Comment gérer les effets concurrents dans Flex?
- 19. Comment gérer les paramètres optionnels dans Moose?
- 20. Comment gérer les longues comparaisons dans SQL
- 21. Comment gérer les fuseaux horaires dans CFML?
- 22. Comment gérer les chaînes dans VC++?
- 23. Comment gérer les changements de sérialisation dans .NET 2.0
- 24. Comment gérer un pool d'objets dans Spring?
- 25. Gestion des exceptions dans les appels Ajax
- 26. Comment tracer les exceptions d'objets COM?
- 27. Comment attraper toutes les exceptions d'un WebService?
- 28. Dans WPF, comment gérer un événement dans un ControlTemplate ItemsControl
- 29. Comment gérer un bogue dans VS2008
- 30. Comment gérer les clés api
Une programmation suffisante en Perl est une * programmation procédurale *, mais cela n'en fait pas un langage * procédural *. C'est un langage multi-paradigme. Il permet la programmation OO, mais il emprunte aussi des langages de programmation * fonctionnels *. La seule chose que je ne pense pas pouvoir faire sans beaucoup de travail est la programmation * logique * (comme Prolog). Où 'C' est un langage procédural, et le plus proche que vous pouvez obtenir est en pratiquant et en appliquant la méthodologie des types de données abstraites. – Axeman
@Axeman, voir la distribution AI :: Prolog sur CPAN: http://search.cpan.org/~jjore/AI-Prolog/lib/AI/Prolog.pm – friedo