为什么.NET异常并未被try / catch块? [英] Why is .NET exception not caught by try/catch block?

查看:277
本文介绍了为什么.NET异常并未被try / catch块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 ANTLR 解析器的C#库项目。我已经建立了一个语法解析一些文本,而且运作良好。然而,当分析器遇到一个非法或意外的标记,它引发许多例外之一。问题是,在某些情况下(不是全部),我的try / catch块不会赶上它,而不是停止执行作为未处理的异常。

I'm working on a project using the ANTLR parser library for C#. I've built a grammar to parse some text and it works well. However, when the parser comes across an illegal or unexpected token, it throws one of many exceptions. The problem is that in some cases (not all) that my try/catch block won't catch it and instead stops execution as an unhandled exception.

这个问题对我来说,我不能复制这个问题上任何其他地方,但在我满code。调用堆栈显示异常肯定会出现我的try / catch(异常)块内。我唯一​​能想到的是,有与我的code和code抛出异常并且这个库没有启用调试中发生一些ANTLR组件调用,所以我无法通过它一步。我不知道如果非调试的集会抑制异常冒泡?调用堆栈看起来是这样的;外部组件调用是在Antlr.Runtime:

The issue for me is that I can't replicate this issue anywhere else but in my full code. The call stack shows that the exception definitely occurs within my try/catch(Exception) block. The only thing I can think of is that there are a few ANTLR assembly calls that occur between my code and the code throwing the exception and this library does not have debugging enabled, so I can't step through it. I wonder if non-debuggable assemblies inhibit exception bubbling? The call stack looks like this; external assembly calls are 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#

从解析()最底层调用的code段是这样的:

The code snippet from the bottom-most call in Parse() looks like:

     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(异常)条款应该已经捕获任何任何异常。是否有任何理由为什么不会?

To me, a catch (Exception) clause should've captured any exception whatsoever. Is there any reason why it wouldn't?

更新:我追查通过外部组件与反射器并没有发现任何证据表明任何线程的。装配似乎只是为ANTLR的生成code运行时工具类。引发的异常是从TimeDefLexer.mTokens()方法,它的类型是NoViableAltException,这源于RecognitionException - >例外。这个异常被抛出时,词法无法理解流中的下一个标记;换句话说,无效输入。这一例外是应该发生,但它应该已经被抓住了我的try / catch块。

Update: I traced through the external assembly with Reflector and found no evidence of threading whatsoever. The assembly seems to just be a runtime utility class for ANTLR's generated code. The exception thrown is from the TimeDefLexer.mTokens() method and its type is NoViableAltException, which derives from RecognitionException -> Exception. This exception is thrown when the lexer cannot understand the next token in the stream; in other words, invalid input. This exception is SUPPOSED to happen, however it should've been caught by my try/catch block.

此外,ParserException的重新抛出真的是无关紧要的这种情况。这是解析过程中发生的任何异常,并转化​​为自己的ParserException一个抽象层。异常处理问题我遇到是从来没有达到该行的code。事实上,我评论了抛出新ParserException部分,仍然得到同样的结果。

Also, the rethrowing of ParserException is really irrelevant to this situation. That is a layer of abstraction that takes any exception during parse and convert to my own ParserException. The exception handling problem I'm experiencing is never reaching that line of code. In fact, I commented out the "throw new ParserException" portion and still received the same result.

还有一件事,我修改了原来的try / catch块的问题,而不是赶NoViableAltException,消除任何继承混乱。我仍然收到同样的效果。

One more thing, I modified the original try/catch block in question to instead catch NoViableAltException, eliminating any inheritance confusion. I still received the same result.

曾经有人建议,有时VS是在过度捕捉在调试模式处理的异常,但这个问题也发生在释放模式。

Someone once suggested that sometimes VS is overactive on catching handled exceptions when in debug mode, but this issue also happens in release mode.

男人,我还是难倒!我没有提到过,但我运行VS 2008和所有我的code为3.5。外部组件为2.0。此外,我的一些code的子类的类在2.0组装。难道一个版本不匹配导致此问题?

Man, I'm still stumped! I hadn't mentioned it before, but I'm running VS 2008 and all my code is 3.5. The external assembly is 2.0. Also, some of my code subclasses a class in the 2.0 assembly. Could a version mismatch cause this issue?

更新2:我能消除我的.NET 3.5 code有关的部分,以一个.NET 2.0的项目移植的.NET版本冲突和复制相同的情况。我能当.NET 2.0始终运行复制相同的未处理的异常。

Update 2: I was able to eliminate the .NET version conflict by porting relevant portions of my .NET 3.5 code to a .NET 2.0 project and replicate the same scenario. I was able to replicate the same unhandled exception when running consistently in .NET 2.0.

我了解到ANTLR最近发布3.1。所以,我从3.0.1升级和重试。原来,产生code是一个小重构,但在我的测试情况下出现相同的未处理的异常。

I learned that ANTLR has recently released 3.1. So, I upgraded from 3.0.1 and retried. It turns out the generated code is a little refactored, but the same unhandled exception occurs in my test cases.

更新3: 我在一个简化VS 2008项目复制此方案。随意下载和检查项目的自己。我已经应用了所有伟大的建议,但一直无法克服这个障碍呢。

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.

如果你能找到一个解决办法,请分享你的发现。再次感谢!

If you can find a workaround, please do share your findings. Thanks again!

感谢你,但2008年VS自动断开对未处理的异常。另外,我没有调试 - >例外对话框。时引发的充分准备,并设计了NoViableAltException被抓住用户code。因为它没有被捕获按预期的方式,程序执行意外停止为未处理的异常。

Thank you, but VS 2008 automatically breaks on unhandled exceptions. Also, I don't have a Debug->Exceptions dialog. The NoViableAltException that is thrown is fully intended, and designed to be caught by user code. Since it is not caught as expected, program execution halts unexpectedly as an unhandled exception.

引发的异常从Exception派生,也没有多线程与ANTLR回事。

The exception thrown is derived from Exception and there is no multi-threading going on with ANTLR.

推荐答案

我相信我理解这个问题。唯一的例外是被抓,这个问题是混淆在每个人试图瑞普它之间的调试程序设置调试器的行为和不同之处。

I believe I understand the problem. The exception is being caught, the issue is confusion over the debugger's behavior and differences in the debugger settings among each person trying to repro it.

在您的摄制第三届情况下,我相信你能获得以下消息:NoViableAltException是未处理由用户code和调用堆栈看起来是这样的:

In the 3rd case from your repro I believe you are getting the following message: "NoViableAltException was unhandled by user code" and a callstack that looks like this:


         [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]	

如果你右击在调用堆栈窗口并运行打开显示外部code,你看到这一点:

If you right click in the callstack window and run turn on show external code you see this:


        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

调试器的消息告诉你一个例​​外之外的code原(从NoViableAlt)C你自己的TestAntlr-3.1.exe正在经历$ C $!TimeDefLexer.mTokens()没有被处理。

The debugger's message is telling you that an exception originating outside your code (from NoViableAlt) is going through code you own in TestAntlr-3.1.exe!TimeDefLexer.mTokens() without being handled.

的措辞是混乱的,但它并不意味着例外是未捕获。调试器是让你知道,code你自己mTokens()需要强大的反对这种例外通过它被抛出。

The wording is confusing, but it does not mean the exception is uncaught. The debugger is letting you know that code you own mTokens()" needs to be robust against this exception being thrown through it.

东西玩,看看这个看起来对于那些谁没有瑞普问题:

Things to play with to see how this looks for those who didn't repro the problem:

  • 转到工具/选项/调试和 关闭启用仅我的code (仅限托管)或选项。
  • 转到调试/异常,关闭用户未处理的 共语言运行时异常。
  • Go to Tools/Options/Debugging and turn off "Enable Just My code (Managed only)". or option.
  • Go to Debugger/Exceptions and turn off "User-unhandled" for Common-Language Runtime Exceptions.

这篇关于为什么.NET异常并未被try / catch块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆