56 Stimmen

Warum wird eine .NET-Ausnahme nicht von einem try/catch-Block abgefangen?

Ich arbeite an einem Projekt, das die ANTLR Parser-Bibliothek für C#. Ich habe eine Grammatik gebaut, um etwas Text zu analysieren und es funktioniert gut. Wenn der Parser jedoch auf ein illegales oder unerwartetes Token stößt, löst er eine von vielen Ausnahmen aus. Das Problem ist, dass in einigen Fällen (nicht in allen) mein try/catch-Block sie nicht abfängt und stattdessen die Ausführung als unbehandelte Ausnahme anhält.

Das Problem für mich ist, dass ich dieses Problem nirgendwo anders als in meinem vollständigen Code replizieren kann. Der Aufrufstapel zeigt, dass die Ausnahme definitiv innerhalb meines try/catch(Exception)-Blocks auftritt. Das Einzige, was ich mir vorstellen kann, ist, dass es einige ANTLR-Assembly-Aufrufe gibt, die zwischen meinem Code und dem Code, der die Ausnahme auslöst, liegen, und dass in dieser Bibliothek das Debugging nicht aktiviert ist, sodass ich sie nicht durchgehen kann. Ich frage mich, ob nicht-debuggable Assemblies Exception Bubbling hemmen? Der Aufrufstapel sieht wie folgt aus; externe Assembly-Aufrufe sind in 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#

Der Codeschnipsel des untersten Aufrufs in Parse() sieht folgendermaßen aus:

     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);
     }

Meiner Meinung nach hätte eine catch-Klausel (Exception) jede beliebige Ausnahme auffangen müssen. Gibt es einen Grund, warum das nicht der Fall ist?

Aktualisierung: Ich habe die äußere Baugruppe mit Reflector überprüft und keinerlei Hinweise auf ein Gewinde gefunden. Die Assembly scheint nur eine Laufzeit-Utility-Klasse für den von ANTLR generierten Code zu sein. Die Ausnahme, die ausgelöst wird, stammt von der Methode TimeDefLexer.mTokens() und ist vom Typ NoViableAltException, der sich von RecognitionException -> Exception ableitet. Diese Ausnahme wird ausgelöst, wenn der Lexer das nächste Token im Datenstrom nicht verstehen kann, d. h. wenn die Eingabe ungültig ist. Diese Ausnahme ist SOLLTE passieren, aber es sollte von meinem try/catch-Block abgefangen werden.

Auch das erneute Auslösen von ParserException ist in dieser Situation wirklich irrelevant. Das ist eine Abstraktionsebene, die jede Ausnahme während des Parsens nimmt und in meine eigene ParserException konvertiert. Das Problem der Ausnahmebehandlung, das ich habe, erreicht diese Codezeile nie. Tatsächlich habe ich den Teil "throw new ParserException" auskommentiert und trotzdem das gleiche Ergebnis erhalten.

Eine weitere Sache, änderte ich die ursprüngliche Try/Catch-Block in Frage, um stattdessen NoViableAltException zu fangen, jede Vererbung Verwirrung zu beseitigen. Ich erhielt immer noch das gleiche Ergebnis.

Jemand schlug einmal vor, dass VS im Debug-Modus beim Abfangen von behandelten Ausnahmen manchmal überaktiv ist, aber dieses Problem tritt auch im Release-Modus auf.

Mann, ich bin immer noch ratlos! Ich hatte es vorher nicht erwähnt, aber ich verwende VS 2008 und mein gesamter Code ist 3.5. Die externe Assembly ist 2.0. Außerdem ist ein Teil meines Codes eine Unterklasse einer Klasse in der 2.0-Assembly. Könnte eine Versionsinkongruenz dieses Problem verursachen?

Update 2: Ich konnte den .NET-Versionskonflikt beseitigen, indem ich relevante Teile meines .NET 3.5-Codes auf ein .NET 2.0-Projekt portierte und dasselbe Szenario replizierte. Ich konnte die gleiche unbehandelte Ausnahme replizieren, wenn sie konsequent in .NET 2.0 ausgeführt wurde.

Ich habe erfahren, dass ANTLR kürzlich 3.1 veröffentlicht hat. Also aktualisierte ich von 3.0.1 und versuchte es erneut. Es stellt sich heraus, dass der generierte Code ein wenig umstrukturiert wurde, aber die gleiche unbehandelte Ausnahme tritt in meinen Testfällen auf.

Update 3: Ich habe dieses Szenario in einem vereinfachtes VS 2008-Projekt . Fühlen Sie sich frei, das Projekt herunterzuladen und selbst zu überprüfen. Ich habe all die großartigen Vorschläge umgesetzt, konnte dieses Hindernis aber noch nicht überwinden.

Wenn Sie eine Umgehung finden, teilen Sie uns bitte Ihre Erkenntnisse mit. Nochmals vielen Dank!


Danke, aber VS 2008 bricht automatisch bei unbehandelten Ausnahmen ab. Außerdem habe ich keinen Debug->Exceptions-Dialog. Die NoViableAltException, die ausgelöst wird, ist völlig beabsichtigt und soll vom Benutzercode abgefangen werden. Da sie nicht wie erwartet abgefangen wird, wird die Programmausführung unerwartet als unbehandelte Ausnahme angehalten.

Die geworfene Ausnahme ist von Exception abgeleitet und es gibt kein Multithreading mit ANTLR.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X