Question

Je travaille sur un projet utilisant le ANTLR bibliothèque d'analyseurs pour C#.J'ai construit une grammaire pour analyser du texte et cela fonctionne bien.Cependant, lorsque l'analyseur rencontre un jeton illégal ou inattendu, il renvoie l'une des nombreuses exceptions.Le problème est que dans certains cas (pas tous), mon bloc try/catch ne l'attrapera 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 définitivement dans mon bloc try/catch(Exception).La seule chose à laquelle je peux penser est qu'il y a quelques appels d'assembly ANTLR qui se produisent entre mon code et le code qui lance l'exception et que le débogage n'est pas activé dans cette bibliothèque, je ne peux donc pas la parcourir.Je me demande si les assemblys non déboguables inhibent la propagation des exceptions ?La pile d'appels ressemble à ceci :les appels d'assembly 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 à :

     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 n'importe quelle exception.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 n'ai trouvé aucune preuve de filetage.L'assembly semble être simplement une 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 lexer ne peut pas comprendre le jeton suivant dans le flux ;en d'autres termes, entrée invalide.Cette exception est CENSÉE se produire, mais elle aurait dû être interceptée par mon bloc try/catch.

De plus, la relance de ParserException n’a vraiment aucun rapport avec cette situation.Il s'agit d'une couche d'abstraction qui prend toute exception lors de 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 "lancer un nouveau ParserException" et j'ai toujours reçu le même résultat.

Encore une chose, j'ai modifié le bloc try/catch d'origine en question pour intercepter NoViableAltException, éliminant ainsi toute confusion d'héritage.J'ai toujours reçu le même résultat.

Quelqu'un a suggéré un jour que VS est parfois trop actif pour détecter les exceptions gérées en mode débogage, mais ce problème se produit également en mode release.

Mec, je suis toujours perplexe !Je ne l'avais pas mentionné auparavant, mais j'utilise VS 2008 et tout mon code est 3.5.L'assemblage externe est 2.0.De plus, certains de mes codes sous-classent une classe dans l'assembly 2.0.Une incompatibilité de version pourrait-elle être à l'origine de ce problème ?

Mise à jour 2 : J'ai pu éliminer le conflit de version .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 répliquer la même exception non gérée lors d'une exécution cohérente dans .NET 2.0.

J'ai appris qu'ANTLR avait récemment publié la version 3.1.J'ai donc mis à niveau depuis 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 reproduit ce scénario dans un projet VS 2008 simplifié.N'hésitez pas à télécharger et à inspecter le projet par vous-même.J'ai appliqué toutes les bonnes suggestions, mais je n'ai pas encore réussi à surmonter cet obstacle.

Si vous pouvez trouver une solution de contournement, veuillez partager vos découvertes.Merci encore!


Merci, mais VS 2008 s'arrête automatiquement en cas d'exceptions non gérées.De plus, je n'ai pas de boîte de dialogue Debug->Exceptions.L'exception NoViableAltException levée est entièrement destinée et conçue pour être interceptée par le code utilisateur.Puisqu'il n'est pas intercepté 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 levée est dérivée de Exception et il n'y a pas de multithreading avec ANTLR.

Était-ce utile?

La solution

Je crois que je comprends le problème.L'exception est détectée, le problème est la confusion sur le comportement du débogueur et les différences dans les paramètres du débogueur entre chaque personne essayant de le reproduire.

Dans le 3ème cas de votre repro, je pense que vous recevez le message suivant :"NoViableAltException n'a pas été gérée par le code utilisateur" et une pile d'appels qui ressemble à ceci :

         [External Code]    
    >   TestAntlr-3.1.exe!TimeDefLexer.mTokens() Line 852 + 0xe bytes   C#
        [External Code] 
        TestAntlr-3.1.exe!TimeDefParser.prog() Line 141 + 0x14 bytes    C#
        TestAntlr-3.1.exe!TestAntlr_3._1.Program.ParseTest(string Text = "foobar;") Line 49 + 0x9 bytes C#
        TestAntlr-3.1.exe!TestAntlr_3._1.Program.Main(string[] args = {string[0x00000000]}) Line 30 + 0xb bytes C#
        [External Code] 

Si vous faites un clic droit dans la fenêtre de la pile d'appels et exécutez Turn on Show External Code, vous voyez ceci :

        Antlr3.Runtime.dll!Antlr.Runtime.DFA.NoViableAlt(int s = 0x00000000, Antlr.Runtime.IIntStream input = {Antlr.Runtime.ANTLRStringStream}) + 0x80 bytes   
        Antlr3.Runtime.dll!Antlr.Runtime.DFA.Predict(Antlr.Runtime.IIntStream input = {Antlr.Runtime.ANTLRStringStream}) + 0x21e bytes  
    >   TestAntlr-3.1.exe!TimeDefLexer.mTokens() Line 852 + 0xe bytes   C#
        Antlr3.Runtime.dll!Antlr.Runtime.Lexer.NextToken() + 0xc4 bytes 
        Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.FillBuffer() + 0x147 bytes   
        Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.LT(int k = 0x00000001) + 0x2d bytes  
        TestAntlr-3.1.exe!TimeDefParser.prog() Line 141 + 0x14 bytes    C#
        TestAntlr-3.1.exe!TestAntlr_3._1.Program.ParseTest(string Text = "foobar;") Line 49 + 0x9 bytes C#
        TestAntlr-3.1.exe!TestAntlr_3._1.Program.Main(string[] args = {string[0x00000000]}) Line 30 + 0xb bytes C#
        [Native to Managed Transition]  
        [Managed to Native Transition]  
        mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x39 bytes    
        Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2b bytes  
        mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x3b bytes   
        mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x81 bytes    
        mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x40 bytes

Le message du débogueur vous indique qu'une exception provenant de l'extérieur de votre code (de NoViableAlt) traverse le code que vous possédez dans TestAntlr-3.1.exe!TimeDefLexer.mTokens() sans être gérée.

La formulation prête à confusion, mais cela ne signifie pas que l’exception n’est pas prise en compte.Le débogueur vous informe que le code que vous possédez mTokens()" doit être robuste contre cette exception qui y est émise.

Choses avec lesquelles jouer pour voir à quoi cela ressemble pour ceux qui n'ont pas reproduit le problème :

  • Accédez aux outils / options / débogage et désactivez "Activer Just My Code (géré uniquement)".ou en option.
  • Accédez à Debugger / Exceptions et désactivez "User-Inandled" pour les exceptions d'exécution en langage commun.

Autres conseils

Que l'assembly ait été compilé ou non en tant que version de version, l'exception devrait certainement « buller » jusqu'à l'appelant, il n'y a aucune raison pour qu'un assembly non compilé en mode débogage ait un effet sur cela.

Je suis d'accord avec Daniel qui suggère que l'exception se produit peut-être sur un thread distinct - essayez d'accrocher l'événement d'exception de thread dans Application.ThreadException.Cela doit être déclenché lorsqu'une exception de thread non gérée se produit.Vous pouvez adapter votre code ainsi : -

using System.Threading;

...

void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {
  throw new ParserException(e.Exception.Message, e.Exception);
}    

 ...

 var exceptionHandler = 
    new ThreadExceptionEventHandler(Application_ThreadException);
 Application.ThreadException += exceptionHandler;
 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);
 }
 finally {
    Application.ThreadException -= exceptionHandler;
 }

Utilisez-vous .Net 1.0 ou 1.1 ?Si tel est le cas, catch(Exception ex) n'interceptera pas les exceptions du code non géré.Vous devrez utiliser catch {} à la place.Consultez cet article pour plus de détails :

http://www.netfxharmonics.com/2005/10/net-20-trycatch-and-trycatchexception/

Je peux vous dire ce qui se passe ici...

Visual Studio est en panne car il pense que l'exception n'est pas gérée.Que signifie non géré ?Eh bien, dans Visual Studio, il y a un paramètre dans les outils...Possibilités...Débogage...Général..."Activer Just My Code (géré uniquement)".Si ceci est coché et si l'exception se propage hors de votre code et vers un cadre de pile associé à un appel de méthode qui existe dans un assembly qui n'est "PAS VOTRE CODE" (par exemple, Antlr), cela est considéré comme "non géré".Je désactive cette fonctionnalité Activer uniquement mon code pour cette raison.Mais si vous me demandez, c'est nul...disons que vous faites ceci :

ExternalClassNotMyCode c = new ExternalClassNotMyCode();
try {
    c.doSomething( () => { throw new Exception(); } );
}
catch ( Exception ex ) {}

doSomething y appelle votre fonction anonyme et cette fonction lève une exception...

Notez qu'il s'agit d'une « exception non gérée » selon Visual Studio si « Activer uniquement mon code » est activé.Notez également qu'il s'arrête comme s'il s'agissait d'un point d'arrêt en mode débogage, mais dans un environnement sans débogage ou de production, le code est parfaitement valide et fonctionne comme prévu.De plus, si vous "continuez" simplement dans le débogueur, l'application continue son bon chemin (cela n'arrête pas le fil).Elle est considérée comme "non gérée" car l'exception se propage via un cadre de pile qui n'est PAS dans votre code (c'est-à-diredans la bibliothèque externe).Si vous me demandez, c'est moche.Veuillez modifier ce comportement par défaut Microsoft.Il s'agit d'un cas parfaitement valable d'utilisation d'exceptions pour contrôler la logique du programme.Parfois, vous ne pouvez pas modifier le comportement de la bibliothèque tierce pour qu'elle se comporte autrement, ce qui constitue un moyen très utile d'accomplir de nombreuses tâches.

Prenez MyBatis par exemple, vous pouvez utiliser cette technique pour arrêter le traitement des enregistrements collectés par un appel à SqlMapper.QueryWithRowDelegate.

Est-il possible que l'exception soit levée dans un autre thread ?Évidemment, votre code appelant est monothread, mais peut-être que la bibliothèque que vous consommez effectue des opérations multithread sous les couvertures.

Je suis avec @Shaun Austin - essayez de terminer l'essai avec le nom complet

catch (System.Exception)

et voyez si cela aide. La documentation ANTLR indique-t-elle quelles exceptions doivent être levées ?

Pour moi, une clause catch (Exception) aurait dû capturer n'importe quelle exception.Y a-t-il une raison pour laquelle ce ne serait pas le cas ?

La seule possibilité à laquelle je peux penser est que quelque chose d'autre l'attrape avant vous et le gère d'une manière qui semble être une exception non capturée (par ex.sortie du processus).

mon bloc try/catch ne l'attrapera pas et arrête l'exécution en tant qu'exception non gérée.

Vous devez trouver la cause du processus de sortie.Il peut s'agir d'autre chose qu'une exception non gérée.Vous pouvez essayer d'utiliser le débogueur natif avec un point d'arrêt défini sur "{,,kernel32.dll}ExitProcess".Utilisez ensuite SOS pour déterminer quel code managé appelle le processus de sortie.

Personnellement, je ne suis pas du tout convaincu par la théorie du threading.

La seule fois où j'ai vu cela auparavant, je travaillais avec une bibliothèque qui définissait également Exception et les utilisations que j'avais signifiaient que le Catch réel faisait référence à un type "Exception" différent (s'il avait été pleinement qualifié, c'était Company. Lib.Exception mais ce n'était pas à cause de l'utilisation), donc quand il s'agissait d'attraper une exception normale qui était levée (une sorte d'exception d'argument si je me souviens bien), elle ne l'attraperait tout simplement pas parce que le type ne correspondait pas.

Donc, en résumé, existe-t-il un autre type d'exception dans un espace de noms différent qui est utilisé dans cette classe ?

MODIFIER:Un moyen rapide de vérifier cela est de vous assurer que dans votre clause catch vous qualifiez entièrement le type d'exception comme "System.Exception" et de lui donner un tourbillon !

EDIT2 :OK, j'ai essayé le code et j'admets ma défaite pour l'instant.Il faudra que je le réexamine demain matin si personne n'a trouvé de solution.

Hmm, je ne comprends pas le problème.J'ai téléchargé et essayé votre exemple de fichier de solution.

Une exception est levée dans TimeDefLexer.cs, ligne 852, qui est ensuite gérée par le bloc catch dans Program.cs qui dit simplement Exception gérée.

Si je décommente le bloc catch au-dessus, il entrera dans ce bloc à la place.

Quel semble être le problème ici?

Comme l'a dit Kibbee, Visual Studio s'arrêtera en cas d'exception, mais si vous lui demandez de continuer, l'exception sera interceptée par votre code.

J'ai téléchargé l'exemple de projet VS2008 et je suis également un peu perplexe ici.J'ai cependant pu contourner les exceptions, même si probablement pas d'une manière qui fonctionnera très bien pour vous.Mais voici ce que j'ai trouvé :

Ce publication sur la liste de diffusion J'ai eu une discussion sur ce qui semble être le même problème que vous rencontrez.

À partir de là, j'ai ajouté quelques classes factices dans le fichier program.cs principal :

class MyNoViableAltException : Exception
{
    public MyNoViableAltException()
    {
    }
    public MyNoViableAltException(string grammarDecisionDescription, int decisionNumber, int stateNumber, Antlr.Runtime.IIntStream input)
    {
    }
}
class MyEarlyExitException : Exception
{
    public MyEarlyExitException()
    {
    }

    public MyEarlyExitException(int decisionNumber, Antlr.Runtime.IIntStream input)
    {
    }
}

puis j'ai ajouté les lignes using dans TimeDefParser.cs et TimeDefLexer.cs :

using NoViableAltException = MyNoViableAltException;
using EarlyExitException = NoViableAltException; 

Avec cela, les exceptions bouillonneraient dans les fausses classes d'exceptions et pourraient y être gérées, mais une exception était toujours levée dans la méthode mTokens dans TimeDefLexer.cs.Envelopper cela dans un try catch dans cette classe a détecté l'exception :

            try
            {
                alt4 = dfa4.Predict(input);
            }
            catch
            {
            }

Je ne comprends vraiment pas pourquoi l'envelopper dans la méthode interne plutôt que d'où il est appelé pour gérer l'erreur si le threading n'est pas en jeu, mais de toute façon, j'espère que cela dirigera quelqu'un de plus intelligent que moi ici dans la bonne direction.

J'ai téléchargé votre code et tout fonctionne comme prévu.

Le débogueur Visual Studio intercepte correctement toutes les exceptions.Les blocs Catch fonctionnent comme prévu.

J'utilise le serveur Windows 2003 SP2, VS2008 Team Suite (9.0.30729.1 SP)

J'ai essayé de compiler votre projet pour .NET 2.0, 3.0 et 3.5

@Steve Steiner, les options du débogueur que vous avez mentionnées n'ont rien à voir avec ce comportement.

J'ai essayé de jouer avec ces options sans effets visibles - les blocs catch ont réussi à intercepter toutes les exceptions.

Steve Steiner a raison de dire que l'exception provient de la bibliothèque antlr, passe par la méthode mTokens() et est interceptée dans la bibliothèque antlr.Le problème est que cette méthode est générée automatiquement par antlr.Par conséquent, toute modification visant à gérer l'exception dans mTokens() sera écrasée lorsque vous générerez vos classes d'analyseur/lexer.

Par défaut, antlr enregistrera les erreurs et tentera de récupérer l'analyse.Vous pouvez remplacer cela afin que parser.prog() lève une exception chaque fois qu'une erreur est rencontrée.D'après votre exemple de code, je pense que c'est le comportement que vous attendiez.

Ajoutez ce code à votre fichier grammer (.g).Vous devrez également désactiver « Activer Just My Code » dans le menu de débogage.

@members {

    public override Object RecoverFromMismatchedSet(IIntStream input,RecognitionException e,    BitSet follow)  
    {
        throw e;
    }
}

@rulecatch {
    catch (RecognitionException e) 
    {
        throw e;
    }
}

Il s'agit de ma tentative de version C# de l'exemple donné dans le chapitre "Quitter le système de reconnaissance à la première erreur" du livre "Definitive ANTLR Reference".

J'espère que c'est ce que vous cherchiez.

Vous pouvez configurer VS.Net pour qu'il s'arrête dès qu'une exception se produit.Exécutez simplement votre projet en mode débogage et il s’arrêtera dès que l’exception sera levée.Vous devriez alors avoir une meilleure idée de la raison pour laquelle il n’est pas détecté.

Vous pouvez également insérer du code dans intercepter toutes les exceptions non gérées.Lisez le lien pour plus d'informations, mais les bases sont ces deux lignes.

Application.ThreadException += new ThreadExceptionEventHandler(ThreadExceptionHandler);

 // Catch all unhandled exceptions in all threads.
 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler);

Oh et en référence à ce que Kibbee a dit :si vous sélectionnez Debug | Exceptions dans VS et cliquez simplement sur toutes les cases de la colonne « lancée », il devrait choisir tout considère l'AFAIK comme une « exception de première chance », c'est-à-direVS indiquera quand l'exception est à propos être traité par tout le reste et s'arrêter sur le code correspondant.Cela devrait aider au débogage.

La meilleure option ressemble à configurer Visual Studio pour qu'il interrompe toutes les exceptions non gérées (boîte de dialogue Débogage -> Exceptions, cochez la case "Exceptions Common Language Runtime" et éventuellement les autres également).Exécutez ensuite votre programme en mode débogage.Lorsque le code de l'analyseur ANTLR génère une exception, celle-ci doit être interceptée par Visual Studio et vous permettre de voir où elle se produit, le type d'exception, etc.

D'après la description, le bloc catch semble être correct, donc plusieurs choses pourraient se produire :

  1. l'analyseur ne lève pas réellement d'exception
  2. l'analyseur lance finalement quelque chose qui ne dérive pas de System.Exception
  3. une exception est levée sur un autre thread qui n'est pas géré

Il semble que vous ayez potentiellement exclu le problème n°3.

J'ai parcouru l'assemblage externe avec Reflector et n'ai trouvé aucune preuve de filetage.

Vous ne trouvez aucun thread, cela ne veut pas dire qu'il n'y a pas de thread

.NET dispose d'un « pool de threads », qui est un ensemble de threads « de rechange » qui restent pour la plupart inactifs.Certaines méthodes entraînent l'exécution d'éléments dans l'un des threads du pool de threads afin de ne pas bloquer votre application principale.

Les exemples flagrants sont des choses comme ThreadPool.QueueUserWorkItem, mais il y a beaucoup d'autres choses qui peuvent également exécuter des choses dans le pool de threads qui ne semblent pas si évidentes, comme Délégué.BeginInvoke

Vraiment, tu dois fais ce que Kibbee suggère.

avez-vous essayé d'imprimer (Console.WriteLine()) l'exception à l'intérieur de la clause catch, et de ne pas utiliser Visual Studio et d'exécuter votre application sur la console ?

Je pense que Steve Steiner a raison.En recherchant les suggestions de Steve, je suis tombé sur ce fil parler de l'option "Activer uniquement mon code" dans Outils | Options | Débogueur | Général.Il est suggéré que le débogueur s'arrête dans certaines conditions lorsque du code non utilisateur lève ou gère une exception.Je ne sais pas exactement pourquoi cela est important, ni pourquoi le débogueur dit spécifiquement que l'exception n'a pas été gérée alors qu'elle l'était réellement.

J'ai pu éliminer les fausses coupures en désactivant l'option "Activer uniquement mon code".Cela modifie également la boîte de dialogue Debug|Exceptions en supprimant la colonne « Géré par l'utilisateur » car elle ne s'applique plus.Ou, vous pouvez simplement décocher la case "Géré par l'utilisateur" pour CLR et obtenir le même résultat.

Un grand merci pour l'aide à tous !

"En outre, vous pouvez mettre du code pour attraper toutes les exceptions non gérées.Lisez le lien pour plus d'informations, mais les bases sont ces deux lignes. "

C'est faux.Cela interceptait toutes les exceptions non gérées dans .NET 1.0/1.1, mais c'était un bug et ce n'était pas censé le faire et il a été corrigé dans .NET 2.0.

AppDomain.CurrentDomain.UnhandledException 

Est uniquement destiné à être utilisé comme salle de journalisation de la dernière chance afin que vous puissiez enregistrer l'exception avant la fermeture du programme.Il n'attrapera pas l'exception à partir de la version 2.0 (bien que dans .NET 2.0 au moins, il existe une valeur de configuration que vous pouvez modifier pour la faire agir comme 1.1, mais ce n'est pas une pratique recommandée de l'utiliser.).

Il convient de noter qu'il existe quelques exceptions auxquelles vous ne peut pas catch, tels que StackOverflowException et OutOfMemoryException.Sinon, comme d'autres personnes l'ont suggéré, cela pourrait être une exception dans un fil de discussion en arrière-plan quelque part.De plus, je suis presque sûr que vous ne pouvez pas non plus détecter certaines/toutes les exceptions non gérées/natives.

Je ne comprends pas... votre bloc catch lève simplement une nouvelle exception (avec le même message).Cela signifie que votre déclaration de :

Le problème est que dans certains cas (pas tous), mon bloc try/catch ne l'attrapera pas et arrête l'exécution en tant qu'exception non gérée.

c'est exactement ce qui est attendu se passer.

je suis d'accord avec Daniel Auger et couronne que cela ressemble à une exception qui a quelque chose à voir avec les threads.Au-delà de cela, voici mes autres questions :

  1. Que dit le message d'erreur complet ?De quel genre d’exception s’agit-il ?
  2. Sur la base de la trace de pile que vous avez fournie ici, l'exception levée par votre code dans TimeDefLexer.mTokens() n'est-elle pas ?

Je ne sais pas si je ne suis pas clair, mais si c'est le cas, je vois le débogueur interrompre l'exécution avec une "exception non gérée" de type NoViableAltException.Au départ, je ne savais rien de cet élément de menu Debug->Exceptions, car MS s'attend à ce que vous, au moment de l'installation de VS, vous engagez dans un profil lorsque vous n'avez aucune idée de leur différence.Apparemment, Je n'étais pas sur le profil de développement C# et il me manquait cette option.Après avoir finalement débogué toutes les exceptions CLR levées, je n'ai malheureusement pas pu découvrir de nouveau comportement conduisant à la raison de ce problème d'exception non géré.Toutes les exceptions levées étaient attendues et censées être gérées dans un bloc try/catch.

J'ai examiné l'assemblage externe et il n'y a aucune preuve de multithreading.Par cela, je veux dire qu’aucune référence n’existe à System.Threading et qu’aucun délégué n’a été utilisé.Je sais que cela constitue l'instanciation d'un fil.Je vérifie cela en observant la boîte à outils Threads au moment de l'exception non gérée pour voir qu'il n'y a qu'un seul thread en cours d'exécution.

J'ai un problème ouvert avec les gens d'ANTLR, alors peut-être qu'ils ont déjà pu résoudre ce problème auparavant.J'ai pu le reproduire dans un simple projet d'application console utilisant .NET 2.0 et 3.5 sous VS 2008 et VS 2005.

C'est juste un problème car cela oblige mon code à fonctionner uniquement avec une entrée d'analyseur valide et connue.Utiliser un IsValid() La méthode serait risquée si elle lançait une exception non gérée basée sur l’entrée de l’utilisateur.Je garderai cette question à jour lorsque nous en saurons davantage sur ce problème.

@spouson,

Si vous pouvez le reproduire, pouvez-vous le publier quelque part ?Une solution que vous pouvez essayer consiste à utiliser WinDBG avec les extensions SOS pour exécuter l'application et intercepter l'exception non gérée.Il s'arrêtera à la première exception (avant que le runtime n'essaye de trouver un gestionnaire) et vous pourrez voir à ce stade d'où il vient et de quel thread.

Si vous n'avez jamais utilisé WinDBG auparavant, cela peut être un peu écrasant, mais voici un bon tutoriel :

http://blogs.msdn.com/johan/archive/2007/11/13/getting-started-with-windbg-part-i.aspx

Une fois que vous démarrez WinDBG, vous pouvez activer/désactiver la suppression des exceptions non gérées en accédant à Debug->Event Filters.

Wow, parmi les rapports jusqu'à présent, 2 ont fonctionné correctement et 1 a rencontré le problème que j'ai signalé.Quelles sont les versions de Windows, de Visual Studio utilisées et du framework .NET avec les numéros de build ?

J'utilise XP SP2, VS 2008 Team Suite (9.0.30729.1 SP), C# 2008 (91899-270-92311015-60837) et .NET 3.5 SP1.

Si vous utilisez des objets com dans votre projet et que vous essayez de capturer des blocs pour ne pas intercepter les exceptions, vous devrez désactiver l'option Outils/Débogage/Break lorsque les exceptions traversent le domaine d'application ou les limites gérées/natives (gérées uniquement).

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