Je travaille sur un projet utilisant le ANTLR pour C#. J'ai construit une grammaire pour analyser du texte et cela fonctionne bien. Cependant, lorsque le parseur rencontre un token illégal ou inattendu, il lève l'une des nombreuses exceptions. Le problème est que dans certains cas (pas tous), mon bloc try/catch ne l'attrape pas et arrête l'exécution en tant qu'exception non gérée.
Le problème pour moi est que je ne peux pas reproduire ce problème ailleurs que dans mon code complet. La pile d'appels montre que l'exception se produit bien dans mon bloc try/catch(Exception). La seule chose à laquelle je peux penser est qu'il y a quelques appels d'assemblage ANTLR qui se produisent entre mon code et le code qui lance l'exception et cette bibliothèque n'a pas de débogage activé, donc je ne peux pas passer à travers. Je me demande si les assemblages non débuggeables empêchent le bouillonnement des exceptions ? La pile d'appels ressemble à ceci ; les appels d'assemblages externes sont dans Antlr.Runtime :
Expl.Itinerary.dll!TimeDefLexer.mTokens() Line 1213 C#
Antlr3.Runtime.dll!Antlr.Runtime.Lexer.NextToken() + 0xfc bytes
Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.FillBuffer() + 0x22c bytes
Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.LT(int k = 1) + 0x68 bytes
Expl.Itinerary.dll!TimeDefParser.prog() Line 109 + 0x17 bytes C#
Expl.Itinerary.dll!Expl.Itinerary.TDLParser.Parse(string Text = "", Expl.Itinerary.IItinerary Itinerary = {Expl.Itinerary.MemoryItinerary}) Line 17 + 0xa bytes C#
L'extrait de code de l'appel le plus bas dans Parse() ressemble à ceci :
try {
// Execution stopped at parser.prog()
TimeDefParser.prog_return prog_ret = parser.prog();
return prog_ret == null ? null : prog_ret.value;
}
catch (Exception ex) {
throw new ParserException(ex.Message, ex);
}
Pour moi, une clause catch (Exception) aurait dû capturer toute exception quelle qu'elle soit. Y a-t-il une raison pour laquelle ce ne serait pas le cas ?
Mise à jour : J'ai parcouru l'assemblage externe avec Reflector et je n'ai trouvé aucune trace de filetage. L'assemblage semble être une simple classe utilitaire d'exécution pour le code généré par ANTLR. L'exception levée provient de la méthode TimeDefLexer.mTokens() et son type est NoViableAltException, qui dérive de RecognitionException -> Exception. Cette exception est levée lorsque le lexeur ne peut pas comprendre le token suivant dans le flux ; en d'autres termes, une entrée invalide. Cette exception est SUPPOSÉE à se produire, mais elle aurait dû être attrapée par mon bloc try/catch.
De plus, le rejet de l'exception ParserException n'est pas vraiment pertinent dans cette situation. Il s'agit d'une couche d'abstraction qui prend toute exception pendant l'analyse et la convertit en ma propre ParserException. Le problème de gestion des exceptions que je rencontre n'atteint jamais cette ligne de code. En fait, j'ai commenté la partie "throw new ParserException" et j'ai toujours obtenu le même résultat.
Une dernière chose, j'ai modifié le bloc try/catch original en question pour attraper plutôt NoViableAltException, éliminant ainsi toute confusion d'héritage. J'ai toujours obtenu le même résultat.
Quelqu'un a suggéré que parfois VS est trop actif pour attraper les exceptions manipulées en mode débogage, mais ce problème se produit également en mode release.
Mec, je suis toujours en panne ! Je ne l'avais pas encore mentionné, mais j'utilise VS 2008 et tout mon code est en 3.5. L'assemblage externe est 2.0. De plus, une partie de mon code sous-classe une classe dans l'assemblage 2.0. Un décalage de version pourrait-il causer ce problème ?
Mise à jour 2 : J'ai pu éliminer le conflit de version de .NET en portant les parties pertinentes de mon code .NET 3.5 vers un projet .NET 2.0 et en reproduisant le même scénario. J'ai pu reproduire la même exception non gérée lors d'une exécution cohérente en .NET 2.0.
J'ai appris qu'ANTLR a récemment publié la version 3.1. J'ai donc mis à jour la version 3.0.1 et j'ai réessayé. Il s'avère que le code généré est un peu remanié, mais la même exception non gérée se produit dans mes cas de test.
Mise à jour 3 : J'ai répliqué ce scénario dans une projet VS 2008 simplifié . N'hésitez pas à télécharger et à examiner le projet par vous-même. J'ai appliqué toutes les excellentes suggestions, mais je n'ai pas encore réussi à surmonter cet obstacle.
Si vous trouvez une solution de contournement, veuillez partager vos conclusions. Merci encore !
Merci, mais VS 2008 s'arrête automatiquement sur les exceptions non gérées. De plus, je n'ai pas de dialogue Debug->Exceptions. L'exception NoViableAltException qui est levée est entièrement prévue et conçue pour être attrapée par le code utilisateur. Comme elle n'est pas détectée comme prévu, l'exécution du programme s'arrête de manière inattendue en raison d'une exception non gérée.
L'exception déclenchée est dérivée de Exception et il n'y a pas de multithreading avec ANTLR.