我正在使用ANTLRC#的解析器库。我已经构建了一个语法来解析一些文本,它运行得很好。然而,当解析器遇到非法或意外的令牌时,它会抛出许多异常之一。问题是,在某些情况下(不是所有情况下),我的try/catch块不会捕获它,而是作为未处理的异常停止执行。
对我来说,问题是除了在我的完整代码中,我不能在其他任何地方复制这个问题。调用堆栈显示异常肯定发生在我的try/catch(exception)块中。我唯一能想到的是,在我的代码和抛出异常的代码之间发生了一些ANTLR程序集调用,而这个库没有启用调试,所以我无法进行调试。我想知道不可调试的程序集是否会抑制异常冒泡?调用堆栈如下所示;外部程序集调用位于Antlr中。运行时:
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#
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->;例外当lexer无法理解流中的下一个令牌时,会引发此异常;换句话说,无效输入。这个异常应该会发生,但是它应该被我的try/catch块捕获。
此外,ParserException的重新思考实际上与这种情况无关。这是一个抽象层,它在解析过程中处理任何异常,并转换为我自己的ParserException。我遇到的异常处理问题是永远不会到达代码的那一行。事实上,我注释掉了“抛出新的ParserException”部分,仍然收到了相同的结果。
还有一件事,我修改了有问题的原始try/catch块,改为捕获NoViableAltException,消除了任何继承混淆。我仍然得到了同样的结果。
有人曾经提出,有时VS在调试模式下捕捉已处理的异常时过于活跃,但这个问题也会在发布模式下发生。
伙计,我还是被难住了!我以前没有提到过,但我正在运行VS2008,我所有的代码都是3.5。外部组件为2.0。此外,我的一些代码在2.0程序集中对一个类进行了子类化。版本不匹配是否会导致此问题?
更新2:我通过将.NET 3.5代码的相关部分移植到.NET 2.0项目并复制相同的场景,消除了.NET版本冲突。在.NET 2.0中一致运行时,我能够复制相同的未处理异常。
我了解到ANTLR最近发布了3.1。因此,我从3.0.1升级并重试。事实证明,生成的代码有点重构,但在我的测试用例中也发生了同样的未处理异常。
Update 3: I ve replicated this scenario in a simplified VS 2008 project. Feel free to download and inspect the project for yourself. I ve applied all the great suggestions, but have not been able to overcome this obstacle yet.
如果你能找到解决办法,请分享你的发现。再次感谢!
谢谢,但VS2008会自动中断未处理的异常。此外,我没有调试->;异常对话框。抛出的NoViableAltException是完全有意的,并且被设计为由用户代码捕获。由于未按预期捕获,因此程序执行会作为未处理的异常意外中止。
抛出的异常是从exception派生的,并且ANTLR没有进行多线程处理。