私はC#用のANTLRパーサーライブラリを使用してプロジェクトに取り組んでいます。私はいくつかのテキストを解析するための文法を構築しました、そしてそれはうまくいきます。ただし、パーサーが不正または予期しないトークンに遭遇すると、多くの例外の1つをスローします。問題は、場合によっては(すべてではない)、try / catchブロックがそれをキャッチせず、代わりに未処理の例外として実行を停止することです。
私にとっての問題は、この問題を他の場所では再現できないことですが、完全なコードでしか再現できません。呼び出しスタックは、例外がtry / catch(Exception)ブロック内で確実に発生することを示しています。私が考えることができる唯一のことは、私のコードと例外をスローするコードの間にいくつかのANTLRアセンブリ呼び出しが発生し、このライブラリではデバッグが有効になっていないため、ステップスルーできないことです。デバッグ不可能なアセンブリが例外バブリングを禁止するのだろうか?呼び出しスタックは次のようになります。外部アセンブリ呼び出しはAntlr.Runtimeにあります:
Expl.Itinerary.dll!TimeDefLexer.mTokens()行1213 C# Antlr3.Runtime.dll!Antlr.Runtime.Lexer.NextToken()+0xfcバイト Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.FillBuffer()+0x22cバイト Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.LT(int k = 1)+0x68バイト Expl.Itinerary.dll!TimeDefParser.prog()行109 + 0x17バイトC# Expl.Itinerary.dll!Expl.Itinerary.TDLParser.Parse(string Text = ""、Expl.Itinerary.IItinerary Itinerary = {Expl.Itinerary.MemoryItinerary})行17 + 0xaバイトC#
Parse()の一番下の呼び出しからのコードスニペットは次のようになります。
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);
}
私にとって、catch(Exception)句は、あらゆる例外をキャプチャする必要がありました。そうしない理由はありますか?
更新: Reflectorを使用して外部アセンブリをトレースしましたが、スレッド化の形跡はまったく見つかりませんでした。アセンブリは、ANTLRで生成されたコードのランタイムユーティリティクラスのようです。スローされる例外はTimeDefLexer.mTokens()メソッドからのものであり、そのタイプはNoViableAltExceptionであり、RecognitionException->Exceptionから派生します。この例外は、レクサーがストリーム内の次のトークンを理解できない場合にスローされます。つまり、入力が無効です。この例外は発生することが想定されていますが、try/catchブロックによってキャッチされているはずです。
また、ParserExceptionの再スローは、この状況とはまったく関係ありません。これは、解析中に例外を受け取り、自分のParserExceptionに変換する抽象化レイヤーです。私が経験している例外処理の問題は、そのコード行に到達することはありません。実際、「新しいParserExceptionをスローする」部分をコメントアウトしても、同じ結果が得られました。
もう1つ、問題の元のtry / catchブロックを変更して、代わりにNoViableAltExceptionをキャッチし、継承の混乱を排除しました。私はまだ同じ結果を受け取りました。
ある人は、デバッグモードでVSが処理された例外をキャッチするのに過度にアクティブになることがあると提案しましたが、この問題はリリースモードでも発生します。
男、私はまだ困惑しています!以前は触れていませんでしたが、VS 2008を実行していて、コードはすべて3.5です。外部アセンブリは2.0です。また、私のコードのいくつかは、2.0アセンブリのクラスをサブクラス化します。バージョンの不一致がこの問題を引き起こす可能性がありますか?
更新2: .NET3.5コードの関連部分を.NET2.0プロジェクトに移植し、同じシナリオを複製することで、.NETバージョンの競合を解消することができました。.NET 2.0で一貫して実行しているときに、同じ未処理の例外を複製することができました。
ANTLRが最近3.1をリリースしたことを知りました。そこで、3.0.1からアップグレードして再試行しました。生成されたコードは少しリファクタリングされていることがわかりましたが、同じ未処理の例外が私のテストケースで発生します。
更新3:このシナリオを簡略化されたVS2008プロジェクト に複製しました。プロジェクトをダウンロードして、自分で調べてみてください。私はすべての素晴らしい提案を適用しましたが、この障害をまだ克服することができていません。
回避策を見つけることができる場合は、調査結果を共有してください。再度、感謝します!
ありがとうございますが、VS2008は未処理の例外で自動的に中断します。また、[デバッグ]->[例外]ダイアログがありません。スローされるNoViableAltExceptionは完全に意図されており、ユーザーコードによってキャッチされるように設計されています。期待どおりにキャッチされないため、未処理の例外としてプログラムの実行が予期せず停止します。
スローされる例外はExceptionから派生したものであり、ANTLRでマルチスレッドが実行されることはありません。