try/catch 블록에서 .NET 예외가 포착되지 않는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/36014

  •  09-06-2019
  •  | 
  •  

문제

저는 다음을 사용하여 프로젝트를 진행하고 있습니다. ANTLR C#용 파서 라이브러리.일부 텍스트를 구문 분석하는 문법을 만들었으며 잘 작동합니다.그러나 파서가 불법적이거나 예상치 못한 토큰을 발견하면 많은 예외 중 하나가 발생합니다.문제는 일부 경우(전부는 아님) 내 try/catch 블록이 이를 포착하지 못하고 대신 처리되지 않은 예외로 실행을 중지한다는 것입니다.

나에게 문제는 이 문제를 전체 코드가 아닌 다른 곳에서는 재현할 수 없다는 것입니다.호출 스택은 try/catch(Exception) 블록 내에서 예외가 확실히 발생함을 보여줍니다.내가 생각할 수 있는 유일한 것은 내 코드와 예외를 발생시키는 코드 사이에 발생하는 몇 가지 ANTLR 어셈블리 호출이 있고 이 라이브러리에는 디버깅이 활성화되어 있지 않으므로 단계별로 진행할 수 없다는 것입니다.디버깅할 수 없는 어셈블리가 예외 버블링을 억제하는지 궁금합니다.호출 스택은 다음과 같습니다.외부 어셈블리 호출은 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#

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이 생성한 코드에 대한 런타임 유틸리티 클래스인 것 같습니다.throw된 예외는 TimeDefLexer.mTokens() 메서드에서 발생하며 해당 유형은 RecognitionException -> Exception에서 파생되는 NoViableAltException입니다.이 예외는 어휘 분석기가 스트림의 다음 토큰을 이해할 수 없을 때 발생합니다.즉, 잘못된 입력입니다.이 예외는 발생할 것으로 예상되지만 내 try/catch 블록에 의해 포착되어야 합니다.

또한 ParserException을 다시 발생시키는 것은 이 상황과 실제로 관련이 없습니다.이는 구문 분석 중에 예외를 받아들이고 내 자신의 ParserException으로 변환하는 추상화 계층입니다.제가 겪고 있는 예외 처리 문제는 해당 코드 줄에 도달하지 못하는 것입니다.사실 "throw new ParserException" 부분을 주석 처리했는데도 여전히 동일한 결과를 받았습니다.

한 가지 더, 문제의 원본 try/catch 블록을 대신 NoViableAltException을 포착하여 상속 혼란을 제거하도록 수정했습니다.나는 여전히 같은 결과를 받았습니다.

누군가가 VS가 디버그 모드에서 처리된 예외를 포착하는 데 과도하게 활동한다고 제안한 적이 있지만 이 문제는 릴리스 모드에서도 발생합니다.

이봐, 난 아직도 어리둥절해!이전에 언급한 적이 없지만 저는 VS 2008을 실행하고 있으며 모든 코드는 3.5입니다.외부 어셈블리는 2.0입니다.또한 내 코드 중 일부는 2.0 어셈블리의 클래스를 하위 클래스로 지정합니다.버전 불일치로 인해 이 문제가 발생할 수 있습니까?

업데이트 2: .NET 3.5 코드의 관련 부분을 .NET 2.0 프로젝트로 이식하고 동일한 시나리오를 복제하여 .NET 버전 충돌을 제거할 수 있었습니다..NET 2.0에서 일관되게 실행할 때 처리되지 않은 동일한 예외를 복제할 수 있었습니다.

ANTLR이 최근 3.1을 출시했다는 것을 알게 되었습니다.그래서 3.0.1에서 업그레이드해서 다시 시도했습니다.생성된 코드가 약간 리팩토링된 것으로 나타났지만 내 테스트 사례에서도 동일한 처리되지 않은 예외가 발생했습니다.

업데이트 3:나는 이 시나리오를 단순화된 VS 2008 프로젝트.프로젝트를 직접 다운로드하고 검사해 보세요.훌륭한 제안을 모두 적용했지만 아직 이 장애물을 극복하지 못했습니다.

해결 방법을 찾으면 결과를 공유해 주세요.다시 한 번 감사드립니다!


감사합니다. 하지만 VS 2008은 처리되지 않은 예외가 발생하면 자동으로 중단됩니다.또한 디버그->예외 대화 상자가 없습니다.발생하는 NoViableAltException은 전적으로 의도되었으며 사용자 코드에 의해 포착되도록 설계되었습니다.예상대로 잡히지 않기 때문에 처리되지 않은 예외로 인해 프로그램 실행이 예기치 않게 중단됩니다.

발생한 예외는 Exception에서 파생되며 ANTLR에서는 멀티스레딩이 진행되지 않습니다.

도움이 되었습니까?

해결책

나는 문제를 이해한다고 믿습니다.예외가 포착되는 경우 문제는 디버거 동작에 대한 혼란과 이를 재현하려는 각 사람의 디버거 설정 차이입니다.

귀하의 재현의 세 번째 사례에서는 다음과 같은 메시지가 표시되는 것 같습니다."NoViableAltException은 사용자 코드에 의해 처리되지 않았습니다." 및 다음과 같은 호출 스택:

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

콜스택 창을 마우스 오른쪽 버튼으로 클릭하고 외부 코드 표시를 실행하면 다음이 표시됩니다.

        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

디버거의 메시지는 코드 외부에서 발생한 예외(NoViableAlt에서)가 처리되지 않고 TestAntlr-3.1.exe!TimeDefLexer.mTokens()에서 소유한 코드를 통과하고 있음을 알려줍니다.

표현이 혼란스럽기는 하지만 예외가 포착되지 않았다는 의미는 아닙니다.디버거는 mTokens()를 소유한 코드가 이 예외를 통해 발생하는 것에 대해 강력해야 함을 알려줍니다.

문제를 재현하지 않은 사람들이 어떻게 보이는지 확인하기 위해 가지고 놀 수 있는 것:

  • 도구/옵션/디버깅으로 이동하여 "내 코드 만 활성화 (관리자 만 사용)"를 끄십시오.또는 옵션.
  • Debugger/Exceptions로 이동하여 일반적인 런타임 예외를 위해 "사용자 분리"를 끄십시오.

다른 팁

어셈블리가 릴리스 빌드로 컴파일되었는지 여부에 관계없이 예외는 확실히 호출자에게 '버블링'되어야 하며 디버그 모드에서 컴파일되지 않는 어셈블리가 이에 영향을 미칠 이유가 없습니다.

나는 Daniel이 아마도 별도의 스레드에서 예외가 발생하고 있다는 제안에 동의합니다. Application.ThreadException에서 스레드 예외 이벤트를 연결해 보십시오.처리되지 않은 스레드 예외가 발생할 때 발생해야 합니다.다음과 같이 코드를 조정할 수 있습니다.

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

.Net 1.0 또는 1.1을 사용하고 있습니까?그렇다면 catch(Exception ex)는 비관리 코드에서 예외를 포착하지 않습니다.대신 catch {}를 사용해야 합니다.자세한 내용은 다음 문서를 참조하세요.

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

여기서 무슨 일이 일어나고 있는지 말해 줄 수 있어요 ...

Visual Studio에서는 예외가 처리되지 않은 것으로 간주하므로 작동이 중단됩니다.처리되지 않은은 무슨 뜻인가요?음, Visual Studio의 도구에는 설정이 있습니다...옵션...디버깅 중...일반적인..."내 코드만 활성화(관리 전용)".이 항목을 선택하고 예외가 코드 외부로 전파되어 "귀하의 코드가 아닌" 어셈블리(예: Antlr)에 존재하는 메서드 호출과 연결된 스택 프레임으로 전파되는 경우 이는 "처리되지 않은" 것으로 간주됩니다.이러한 이유로 내 코드만 활성화 기능을 끕니다.그런데 물어보면 이건 좀 애매한데...당신이 이렇게 한다고 가정해보자:

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

doSomething이 익명 함수를 호출하면 해당 함수에서 예외가 발생합니다.

"내 코드만 사용"이 설정된 경우 Visual Studio에 따르면 이는 "처리되지 않은 예외"입니다.또한 디버그 모드에서는 중단점인 것처럼 중지되지만 비디버깅 또는 프로덕션 환경에서는 코드가 완벽하게 유효하고 예상대로 작동합니다.또한 디버거에서 "계속"하면 앱이 계속해서 즐거운 방식으로 진행됩니다(스레드를 중지하지 않음).예외가 코드에 없는 스택 프레임을 통해 전파되기 때문에 "처리되지 않은" 것으로 간주됩니다(예:외부 라이브러리에서).나에게 묻는다면 이건 형편없는 일이다.Microsoft의 기본 동작을 변경하세요.이는 예외를 사용하여 프로그램 논리를 제어하는 ​​완벽하게 유효한 사례입니다.때로는 다른 방식으로 작동하도록 타사 라이브러리를 변경할 수 없으며 이는 많은 작업을 수행하는 데 매우 유용한 방법입니다.

예를 들어 MyBatis를 사용하면 이 기술을 사용하여 SqlMapper.QueryWithRowDelegate 호출로 수집되는 레코드 처리를 중지할 수 있습니다.

다른 스레드에서 예외가 발생하는 것이 가능합니까?분명히 호출 코드는 단일 스레드이지만 사용 중인 라이브러리가 내부적으로 일부 다중 스레드 작업을 수행하고 있을 수도 있습니다.

저는 @Shaun Austin과 함께 있습니다. 정규화된 이름으로 시도를 래핑해 보세요.

catch (System.Exception)

도움이 되는지 확인해 보세요. ANTLR 문서에 어떤 예외가 발생해야 하는지 나와 있나요?

나에게는 catch(Exception) 절이 모든 예외를 포착했어야 했습니다.그렇지 않을 이유가 있나요?

내가 생각할 수 있는 유일한 가능성은 다른 것이 당신보다 먼저 그것을 잡아서 잡히지 않는 예외처럼 보이는 방식으로 처리하는 것입니다(예:프로세스를 종료합니다).

내 try/catch 블록은 이를 포착하지 못하고 대신 처리되지 않은 예외로 실행을 중지합니다.

종료 프로세스의 원인을 찾아야 합니다.처리되지 않은 예외가 아닌 다른 것일 수도 있습니다."{,,kernel32.dll}ExitProcess"에 중단점이 설정된 기본 디버거를 사용해 볼 수 있습니다.그런 다음 사용 위급 신호 종료 프로세스를 호출하는 관리 코드를 확인합니다.

개인적으로 나는 스레딩 이론에 전혀 확신하지 않습니다.

전에 이것을 본 적이 있는데, 나는 Exception도 정의한 라이브러리로 작업하고 있었고 사용은 실제 Catch가 다른 "예외" 유형을 참조하고 있음을 의미했습니다(완전히 정규화된 경우 Company. Lib.Exception은 사용 때문에 발생한 것이 아니었습니다. 그래서 던져진 일반 예외(제가 올바르게 기억한다면 일종의 인수 예외)를 포착할 때 유형이 일치하지 않기 때문에 포착하지 못했습니다.

요약하자면, 해당 클래스의 using에 있는 다른 네임스페이스에 또 다른 Exception 유형이 있습니까?

편집하다:이를 확인하는 빠른 방법은 catch 절에서 예외 유형을 "System.Exception"으로 완전히 한정하고 한번 시도해 보는 것입니다!

편집2:좋아, 나는 코드를 시도했고 지금은 패배를 인정합니다.아무도 해결책을 찾지 못하면 아침에 다시 살펴봐야 할 것입니다.

흠, 문제를 이해하지 못합니다.예제 솔루션 파일을 다운로드하여 사용해 보았습니다.

TimeDefLexer.cs의 852행에서 예외가 발생하며 이후에 다음과 같은 Program.cs의 catch 블록에 의해 처리됩니다. 처리된 예외.

위에 있는 catch 블록의 주석 처리를 제거하면 해당 블록이 대신 입력됩니다.

여기에 무슨 문제가 있는 것 같나요?

Kibbee가 말했듯이 Visual Studio는 예외 발생 시 중지되지만 계속하도록 요청하면 코드에서 예외가 포착됩니다.

샘플 VS2008 프로젝트를 다운로드했는데 여기서도 약간 당황했습니다.그러나 나는 예외를 극복할 수 있었지만 아마도 당신에게 좋은 방법은 아닐 것입니다.하지만 내가 찾은 것은 다음과 같습니다.

이것 메일링 리스트 게시물 귀하가 겪고 있는 것과 동일한 문제가 무엇인지 논의했습니다.

거기에서 기본 program.cs 파일에 몇 가지 더미 클래스를 추가했습니다.

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

그런 다음 TimeDefParser.cs 및 TimeDefLexer.cs에 사용 줄을 추가했습니다.

using NoViableAltException = MyNoViableAltException;
using EarlyExitException = NoViableAltException; 

이를 통해 예외는 가짜 예외 클래스에 버블링되어 처리될 수 있지만 TimeDefLexer.cs의 mTokens 메서드에는 여전히 예외가 발생했습니다.해당 클래스의 try catch로 래핑하면 예외가 발생합니다.

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

스레딩이 작동하지 않는 경우 오류를 처리하기 위해 호출되는 위치가 아닌 내부 메서드로 래핑하는 이유를 정말로 모르겠습니다. 그러나 어쨌든 이것이 나보다 똑똑한 사람이 여기에서 올바른 방향을 가리킬 수 있기를 바랍니다.

귀하의 코드를 다운로드했는데 모든 것이 예상대로 작동합니다.

Visual Studio 디버거는 모든 예외를 올바르게 가로챕니다.Catch 블록은 예상대로 작동합니다.

저는 Windows 2003 서버 SP2, VS2008 Team Suite(9.0.30729.1 SP)를 실행하고 있습니다.

.NET 2.0, 3.0 및 3.5용 프로젝트를 컴파일하려고 했습니다.

@Steve Steiner, 언급한 디버거 옵션은 이 동작과 관련이 없습니다.

저는 눈에 띄는 효과 없이 이러한 옵션을 사용해 보았습니다. catch 블록이 모든 예외를 차단했습니다.

Steve Steiner는 예외가 antlr 라이브러리에서 발생하여 mTokens() 메서드를 통과하고 antlr 라이브러리에서 포착된다는 것이 맞습니다.문제는 이 메서드가 antlr에 의해 자동 생성된다는 것입니다.따라서 mTokens()에서 예외를 처리하기 위한 모든 변경 사항은 파서/렉서 클래스를 생성할 때 덮어쓰게 됩니다.

기본적으로 antlr은 오류를 기록하고 구문 분석 복구를 시도합니다.오류가 발생할 때마다 parser.prog()가 예외를 발생시키도록 이를 재정의할 수 있습니다.귀하의 예제 코드에서 이것이 귀하가 기대했던 동작이라고 생각합니다.

이 코드를 Grammer(.g) 파일에 추가하세요.또한 디버깅 메뉴에서 "내 코드만 활성화"를 꺼야 합니다.

@members {

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

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

이것은 "Definitive ANTLR Reference" 책의 "첫 번째 오류 시 인식기 종료" 장에 제공된 예제의 C# 버전에 대한 나의 시도입니다.

이것이 당신이 찾고 있던 것이기를 바랍니다.

예외가 발생하는 즉시 중단되도록 VS.Net을 설정할 수 있습니다.디버그 모드에서 프로젝트를 실행하면 예외가 발생하는 즉시 중지됩니다.그러면 왜 잡히지 않는지 더 잘 알 수 있을 것입니다.

또한 처리되지 않은 모든 예외를 잡아라.자세한 내용은 링크를 읽어보세요. 기본 사항은 이 두 줄입니다.

Application.ThreadException += new ThreadExceptionEventHandler(ThreadExceptionHandler);

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

아 그리고 Kibbee가 말한 것과 관련하여;VS에서 Debug|Exceptions를 선택하고 'thrown' 열에 있는 모든 상자를 클릭하면 선택됩니다. 모든 것 AFAIK를 '첫 번째 예외'로 설정합니다.VS는 예외가 언제 발생하는지 나타냅니다. ~에 대한 다른 모든 것에 의해 처리되고 관련 코드가 중단됩니다.이는 디버깅에 도움이 될 것입니다.

가장 좋은 옵션은 처리되지 않은 모든 예외를 중단하도록 Visual Studio를 설정하는 것과 같습니다(디버그 -> 예외 대화 상자에서 "공용 언어 런타임 예외" 확인란을 선택하고 다른 항목도 선택 가능).그런 다음 디버그 모드에서 프로그램을 실행하십시오.ANTLR 파서 코드가 예외를 발생시키면 Visual Studio에서 이를 포착하여 발생 위치, 예외 유형 등을 확인할 수 있습니다.

설명에 따르면 catch 블록이 올바른 것으로 나타나므로 다음 중 하나가 발생할 수 있습니다.

  1. 파서는 실제로 예외를 발생시키지 않습니다.
  2. 파서가 궁극적으로 System.Exception에서 파생되지 않은 항목을 던지고 있습니다.
  3. 처리되지 않는 다른 스레드에서 예외가 발생하고 있습니다.

문제 #3을 잠재적으로 배제한 것 같습니다.

Reflector를 사용하여 외부 어셈블리를 추적한 결과 나사산이 있다는 증거는 전혀 발견되지 않았습니다.

스레딩을 찾을 수 없다고 해서 스레딩이 없다는 의미는 아닙니다.

.NET에는 대부분 유휴 상태로 있는 '예비' 스레드 집합인 '스레드 풀'이 있습니다.특정 메서드를 사용하면 스레드 풀 스레드 중 하나에서 작업이 실행되어 기본 앱을 차단하지 않습니다.

노골적인 예는 다음과 같습니다. ThreadPool.QueueUserWorkItem, 하지만 스레드 풀에서 그다지 명확해 보이지 않는 작업을 실행할 수 있는 다른 작업도 많이 있습니다. Delegate.BeginInvoke

정말로, 당신은해야합니다 키비가 제안하는 대로 하세요.

Visual Studio를 사용하지 않고 콘솔에서 응용 프로그램을 실행하지 않고 catch 절 내에서 예외를 인쇄(Console.WriteLine())하려고 했습니까?

나는 스티브 스타이너가 옳다고 믿는다.Steve의 제안을 조사할 때 나는 우연히 발견했습니다. 이 스레드 Tools|Options|Debugger|General의 "Enable Just My Code" 옵션에 대해 이야기하고 있습니다.사용자가 아닌 코드가 예외를 발생시키거나 처리할 때 특정 조건에서 디버거가 중단되는 것이 좋습니다.이것이 왜 중요한지, 또는 왜 디버거가 실제로 예외가 처리되지 않았는데도 예외가 처리되지 않았다고 구체적으로 말하는지 정확히 모르겠습니다.

"내 코드만 활성화" 옵션을 비활성화하여 잘못된 중단을 제거할 수 있었습니다.또한 더 이상 적용되지 않는 "사용자 처리" 열을 제거하여 Debug|Exceptions 대화 상자를 변경합니다.또는 CLR에 대한 "사용자 처리" 상자를 선택 취소하고 동일한 결과를 얻을 수도 있습니다.

모두에게 도움을 주셔서 감사합니다!

"또한 처리되지 않은 모든 예외를 포착하기 위해 일부 코드를 넣을 수 있습니다.자세한 정보는 링크를 읽지 만 기본 사항은이 두 줄입니다. "

이것은 거짓입니다.이는 .NET 1.0/1.1에서 처리되지 않은 모든 예외를 포착하는 데 사용되었지만 이는 버그였으며 예상되지 않았으며 .NET 2.0에서 수정되었습니다.

AppDomain.CurrentDomain.UnhandledException 

프로그램이 종료되기 전에 예외를 기록할 수 있도록 최후의 기회 로깅 살롱으로만 사용하기 위한 것입니다.2.0부터는 예외를 포착하지 않습니다. (비록 .NET 2.0에는 적어도 1.1처럼 작동하도록 수정할 수 있는 구성 값이 있지만 이를 사용하는 것은 권장되지 않습니다.)

몇 가지 예외가 있다는 점은 주목할 가치가 있습니다. 할 수 없다 StackOverflowException 및 OutOfMemoryException과 같은 catch를 사용합니다.그렇지 않으면 다른 사람들이 제안한 것처럼 어딘가의 백그라운드 스레드에서 예외가 될 수 있습니다.또한 관리되지 않는/네이티브 예외 중 일부/전체를 잡을 수 없다고 확신합니다.

이해가 안 돼요...catch 블록에서 (동일한 메시지와 함께) 새로운 예외가 발생합니다.귀하의 진술은 다음과 같습니다.

문제는 일부 경우(전부는 아님) 내 try/catch 블록이 이를 포착하지 못하고 대신 처리되지 않은 예외로 실행을 중지한다는 것입니다.

정확히 무엇입니까 예상되는 일어날.

나는 동의한다 다니엘 오거 그리고 크로노즈 이것은 스레드와 관련된 예외적인 냄새가 납니다.그 외에 다른 질문은 다음과 같습니다.

  1. 전체 오류 메시지는 무엇을 말합니까?어떤 종류의 예외인가요?
  2. 여기에 제공한 스택 추적에 따르면 TimeDefLexer.mTokens()의 코드에서 발생한 예외가 아닌가요?

제가 명확하지 않은지 잘 모르겠지만 그렇다면 디버거가 NoViableAltException 유형의 "처리되지 않은 예외"와 함께 실행을 중단하는 것을 볼 수 있습니다.처음에는 이 디버그->예외 메뉴 항목에 대해 아무것도 몰랐습니다. 왜냐하면 MS에서는 VS 설치 시 프로파일이 어떻게 다른지 모를 때 프로필에 커밋할 것으로 기대하기 때문입니다.보기에, C# 개발자 프로필에 있지 않아서 이 옵션이 누락되었습니다..발생한 모든 CLR 예외를 마침내 디버깅한 후에는 불행하게도 이 처리되지 않은 예외 문제의 원인이 되는 새로운 동작을 발견할 수 없었습니다.발생한 모든 예외는 예상되었으며 try/catch 블록에서 처리되는 것으로 추정됩니다.

외부 어셈블리를 검토했는데 멀티스레딩에 대한 증거가 없습니다.즉, System.Threading에 대한 참조가 없으며 대리자가 전혀 사용되지 않았음을 의미합니다.나는 스레드를 인스턴스화하는 것을 잘 알고 있습니다.처리되지 않은 예외 발생 시 스레드 도구 상자를 관찰하여 실행 중인 스레드가 하나만 있는지 확인하여 이를 확인합니다.

ANTLR 사람들과 미해결 문제가 있으므로 아마도 그들은 이전에 이 문제를 해결할 수 있었을 것입니다.VS 2008 및 VS 2005에서 .NET 2.0 및 3.5를 사용하여 간단한 콘솔 앱 프로젝트에서 이를 복제할 수 있었습니다.

내 코드가 알려진 유효한 파서 입력에서만 작동하도록 강제하기 때문에 이는 단지 문제일 뿐입니다.사용하기 IsValid() 사용자 입력에 따라 처리되지 않은 예외가 발생하는 경우 메서드는 위험할 수 있습니다.이 문제에 대해 더 많은 정보가 나오면 이 질문을 최신 상태로 유지하겠습니다.

@spoulson,

복제할 수 있다면 어딘가에 게시할 수 있나요?시도해 볼 수 있는 한 가지 방법은 SOS 확장과 함께 WinDBG를 사용하여 앱을 실행하고 처리되지 않은 예외를 포착하는 것입니다.첫 번째 예외(런타임이 핸들러를 찾으려고 시도하기 전)에서 중단되며 해당 지점에서 해당 예외가 어디에서 왔는지, 어떤 스레드인지 확인할 수 있습니다.

이전에 WinDBG를 사용해 본 적이 없다면 다소 부담스러울 수 있지만 여기에 좋은 튜토리얼이 있습니다.

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

WinDBG를 시작하면 디버그->이벤트 필터로 이동하여 처리되지 않은 예외 중단을 전환할 수 있습니다.

와, 지금까지 보고된 내용 중 2개는 올바르게 작동했고, 1개는 제가 보고한 문제를 경험했습니다.빌드 번호가 포함된 Windows, 사용된 Visual Studio 및 .NET Framework의 버전은 무엇입니까?

저는 XP SP2, VS 2008 Team Suite(9.0.30729.1 SP), C# 2008(91899-270-92311015-60837) 및 .NET 3.5 SP1을 실행하고 있습니다.

프로젝트에서 com 개체를 사용하고 예외를 포착하지 않는 catch 블록을 시도하는 경우 예외가 AppDomain 또는 관리/네이티브 경계(관리 전용)를 넘을 때 도구/디버깅/중단 옵션을 비활성화해야 합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top