Question

Existe-t-il un bon moyen de savoir quelles exceptions une procédure / fonction peut déclencher dans Delphi (y compris les procédures / fonctions)?

En Java, vous devez toujours déclarer quelles exceptions peuvent être émises, mais ce n'est pas le cas dans Delphi, ce qui pourrait conduire à des exceptions non gérées.

Existe-t-il des outils d'analyse de code permettant de détecter les exceptions non gérées?

Était-ce utile?

La solution

(Edit: il est maintenant évident que la question concernait uniquement la vérification au moment du design).

Nouvelle réponse:

Je ne peux pas vous dire s'il existe des outils pour vérifier cela pour vous. Pascal Analyzer, pour sa part, ne le fait pas.

Je peux vous dire, cependant, que dans la plupart des applications Delphi, même s'il existait un outil permettant de vérifier cela pour vous, vous n'obtiendriez aucun résultat.

Pourquoi? , car la boucle de message principale dans TApplication.Run () encapsule tous les appels HandleMessage () dans un bloc de gestion des exceptions, qui intercepte tous les types d'exceptions. Ainsi, vous aurez une exception implicite / par défaut gérant environ 99,999% du code dans la plupart des applications. Et dans la plupart des applications, cette gestion des exceptions représentera environ 100% de votre propre code. Les 0,001% de code qui ne sont pas encapsulés dans la gestion des exceptions seront le code généré automatiquement.

Si un outil était disponible pour vérifier cela pour vous, vous auriez besoin de réécrire Application.run () de sorte qu'il n'inclue pas la gestion des exceptions.

(Réponse précédente: Le gestionnaire d'événements Application.OnException peut être affecté pour intercepter toutes les exceptions qui ne sont pas gérées par d'autres gestionnaires d'exceptions. Bien qu'il s'agisse d'une exécution, et donc peut-être pas exactement ce que vous recherchez (il semble que vous souhaitiez les identifier au moment de la conception), cela vous permet de capturer toute exception non gérée ailleurs. En conjonction avec des outils tels que les éléments JCLDebug dans la bibliothèque de codes Jedi , vous pouvez enregistrer une trace de pile dans savoir où & amp; pourquoi une exception s'est produite, ce qui permettrait une enquête plus poussée et l'ajout d'une gestion ou d'une prévention spécifique autour du code de culpabilité ... )

Autres conseils

Je suppose que vous essayez de faire que Delphi se comporte comme Java, ce qui n’est pas une bonne approche. Je conseillerais de ne pas trop vous inquiéter des exceptions non gérées. Dans le pire des cas, ils apparaîtront dans le gestionnaire d'exceptions VCL générique et provoqueront une boîte de dialogue de message Windows. Dans une application normale, l'application ne sera pas interrompue.

Un code bien écrit documenterait les différentes exceptions pouvant être levées afin que vous puissiez les gérer de manière significative. Les gestionnaires fourre-tout ne sont pas recommandés car il n'y a vraiment aucun moyen de savoir quoi faire si vous ne savez pas pourquoi une exception a été levée. Je peux aussi fortement recommander madExcept.

Sauf pour un scan sur le " augmenter " mot-clé, il n’existe pas de construction de langage dans Delphi indiquant au lecteur occasionnel quelles exceptions peuvent être attendues d’une méthode.

Au moment de l'exécution, vous pouvez ajouter un gestionnaire d'exception fourre-tout dans chaque méthode, mais cela n'est pas conseillé car cela ralentirait la vitesse d'exécution. (Et c'est aussi fastidieux à faire).

Ajouter un bloc de gestion des exceptions à une méthode va lui ajouter quelques instructions d'assemblage (même si l'exception n'est pas déclenchée), ce qui constitue un ralentissement mesurable lorsque la méthode est appelée très souvent.

Il existe quelques bibliothèques qui peuvent vous aider à analyser les exceptions d'exécution, telles que madExcept , < a href = "http://jcl.svn.sourceforge.net/viewvc/jcl/trunk/jcl/source/windows/JclDebug.pas?view=markup" rel = "nofollow noreferrer"> JclDebug , et EurekaLog . Ces outils peuvent enregistrer toutes sortes de détails sur l'exception, il est vivement conseillé d'utiliser l'un de ceux-ci!

La réponse courte est qu’aucun outil ne fait ce que vous dites, et même une analyse du mot clé augmenter ne vous mènerait pas là-bas. EAccessViolation ou EOutOfMemory ne sont que deux des nombreuses exceptions qui pourraient être levées presque n'importe où.

Un aspect fondamental de Delphi est que les exceptions sont hiérarchiques: toutes les exceptions de langage définies descendent de Exception , bien qu'il soit intéressant de noter qu'il est en fait possible d'élever n'importe quel TObject descendant.

Si vous souhaitez intercepter chaque exception générée dans une procédure particulière, placez-la simplement dans un bloc try / except , mais comme indiqué < em> cela n'est pas recommandé .

// Other code . . . 
try
  SomeProcedure()
except  // BAD IDEA!
  ShowMessage('I caught them all!');
end;

Cela interceptera tout, même les instances d'un TObject surélevé. Bien que je dirais que c'est rarement la meilleure solution. En règle générale, vous souhaitez utiliser un bloc try / finally , puis permettre à votre gestionnaire d'exceptions global (ou à un dernier try / except ) de gérer les exceptions.

Je seconderai (ou c’est le troisième) MadExcept . Je l'utilise avec succès dans plusieurs applications commerciales sans aucun problème. La bonne chose à propos de MadExcept est qu’il générera un rapport pour vous avec une trace complète de la pile qui vous indiquera généralement dans la bonne direction ce qui ne va pas, et peut même inclure une capture d’écran, qui vous sera automatiquement envoyé par courrier électronique. à partir de l'ordinateur client en un simple clic de souris.

Cependant, vous ne voulez pas utiliser ceci pour TOUTES les exceptions, mais simplement pour attraper celles qui vous manquent. Par exemple, si vous ouvrez une base de données et que la connexion échoue, il serait préférable que vous récupériez et traitiez celle-ci vous-même plutôt que de donner à l'utilisateur l'erreur par défaut MadExcept dans votre application.

Toute exception non gérée de manière explicite ou générale à un niveau spécifique se répercutera dans la pile d'appels. Delphi RTL (Run Time Library) générera un ensemble de différentes classes d’exceptions (erreurs mathématiques, erreurs d’accès, erreurs propres à une classe, etc.). Vous pouvez choisir de les traiter de manière spécifique ou générale dans les différents essais sauf blocs.

Vous n'avez pas vraiment besoin de déclarer de nouvelles classes d'exception, sauf si vous devez propager un contexte fonctionnel spécifique avec l'exception.

Comme l'ont écrit de précédents commentateurs, vous pouvez également ajouter une mère de tous les gestionnaires d'exceptions tels que MadExcept ou EurekaLog pour capturer les imprévus.

modifier: il s'agit d'une assurance globale contre les exceptions non gérées

try
  ThisFunctionMayFail;
except
  // but it sure won't crash the application
  on e:exception
  do begin
    // something sensible to handle the error 
    // or perhaps log and/or display the the generic e.description message
  end
end;

Pour l'exécution, essayez Eurekalog . Je ne sais pas s'il existe un outil pour la conception. Vous aurez plus de difficultés même lorsque vous avez du code tiers sans source. Delphi n’a pas besoin d’attraper les exceptions, vous n’avez donc pas à les déclarer comme en Java.

Ce que je voulais dire, c’est que Delphi n’exige pas qu’une exception soit gérée. Il va juste terminer le programme. EurekaLog permet de consigner les exceptions gérées et non gérées et fournit une mine d'informations sur l'état du programme lorsque l'exception se produit, y compris la ligne de code sur laquelle il s'est produit et la pile d'appels à ce moment-là.

Comme le souligne Jim McKeeth, vous ne pouvez pas obtenir de réponse définitive, mais il me semble que l'on pourrait partiellement répondre à la question par une analyse statique: à partir d'une fonction / procédure particulière, construisez un graphe d'appel. Vérifiez chacune des fonctions de ce graphe d’appel pour une instruction de relance. Cela vous indiquerait, par exemple, que TIdTcpClient.ReadString peut générer un EIdNotConnected (entre autres).

Un analyseur intelligent peut également noter que certains codes utilisent l'opérateur / et incluent EDivByZero comme possibilité, ou qu'une procédure accède à un tableau et inclut ERangeError.

Cette réponse est un peu plus précise que la simple recherche de "relance".

Les sections de finalisation des unités peuvent également générer des exceptions. Celles-ci vont filer, je pense ... et sont aussi un peu problématiques.

Je pense que l'EDI Delphi a une "trace de pile" intégrée. ou "arbre de pile" quelque chose comme.

Cette question me rappelle le jeu TRussianRoulette de Skybuck ... google, son code et sa réponse peuvent aider.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top