Domanda

Sto lavorando a un progetto utilizzando il file ANTLR libreria parser per C#.Ho creato una grammatica per analizzare del testo e funziona bene.Tuttavia, quando il parser incontra un token illegale o inaspettato, genera una delle tante eccezioni.Il problema è che in alcuni casi (non tutti) il mio blocco try/catch non lo rileva e interrompe invece l'esecuzione come eccezione non gestita.

Il problema per me è che non posso replicare questo problema da nessun'altra parte se non nel mio codice completo.Lo stack di chiamate mostra che l'eccezione si verifica sicuramente all'interno del mio blocco try/catch(Exception).L'unica cosa che mi viene in mente è che ci sono alcune chiamate di assembly ANTLR che si verificano tra il mio codice e il codice che lancia l'eccezione e questa libreria non ha il debug abilitato, quindi non posso esaminarlo.Mi chiedo se gli assembly non debuggabili inibiscano il bubbling delle eccezioni?Lo stack di chiamate ha il seguente aspetto;le chiamate di assembly esterne sono 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#

Lo snippet di codice della chiamata più in basso in Parse() è simile a:

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

Per me, una clausola catch (Exception) avrebbe dovuto catturare qualsiasi eccezione.C'è qualche motivo per cui non dovrebbe?

Aggiornamento: Ho analizzato l'assemblaggio esterno con Reflector e non ho trovato alcuna prova di filettatura.L'assembly sembra essere solo una classe di utilità di runtime per il codice generato da ANTLR.L'eccezione generata proviene dal metodo TimeDefLexer.mTokens() e il suo tipo è NoViableAltException, che deriva da RecognitionException -> Exception.Questa eccezione viene lanciata quando il lexer non riesce a comprendere il token successivo nel flusso;in altre parole, input non valido.Si DOVREBBE che questa eccezione accada, tuttavia avrebbe dovuto essere rilevata dal mio blocco try/catch.

Inoltre, il rilancio di ParserException è davvero irrilevante per questa situazione.Questo è un livello di astrazione che accetta qualsiasi eccezione durante l'analisi e la converte nella mia ParserException.Il problema di gestione delle eccezioni che sto riscontrando non raggiunge mai quella riga di codice.In effetti, ho commentato la parte "lancia nuova ParserException" e ho comunque ricevuto lo stesso risultato.

Ancora una cosa, ho modificato il blocco try/catch originale in questione per catturare invece NoViableAltException, eliminando qualsiasi confusione sull'ereditarietà.Ho ancora ricevuto lo stesso risultato.

Qualcuno una volta ha suggerito che a volte VS è iperattivo nel rilevare le eccezioni gestite in modalità debug, ma questo problema si verifica anche in modalità rilascio.

Amico, sono ancora perplesso!Non ne avevo parlato prima, ma sto utilizzando VS 2008 e tutto il mio codice è 3.5.L'assemblaggio esterno è 2.0.Inoltre, alcuni dei miei codici sottoclassano una classe nell'assembly 2.0.Una mancata corrispondenza della versione potrebbe causare questo problema?

Aggiornamento 2: Sono riuscito a eliminare il conflitto di versione di .NET eseguendo il porting di parti rilevanti del mio codice .NET 3.5 su un progetto .NET 2.0 e replicando lo stesso scenario.Sono stato in grado di replicare la stessa eccezione non gestita durante l'esecuzione coerente in .NET 2.0.

Ho appreso che ANTLR ha recentemente rilasciato la versione 3.1.Quindi, ho aggiornato dalla 3.0.1 e ho riprovato.Si scopre che il codice generato è leggermente sottoposto a refactoring, ma nei miei casi di test si verifica la stessa eccezione non gestita.

Aggiornamento 3:Ho replicato questo scenario in a progetto VS 2008 semplificato.Sentiti libero di scaricare e ispezionare tu stesso il progetto.Ho applicato tutti gli ottimi suggerimenti, ma non sono ancora riuscito a superare questo ostacolo.

Se riesci a trovare una soluzione alternativa, condividi i tuoi risultati.Grazie ancora!


Grazie, ma VS 2008 si interrompe automaticamente in caso di eccezioni non gestite.Inoltre, non ho una finestra di dialogo Debug->Eccezioni.La NoViableAltException generata è completamente prevista e progettata per essere rilevata dal codice utente.Poiché non viene rilevato come previsto, l'esecuzione del programma si interrompe inaspettatamente a causa di un'eccezione non gestita.

L'eccezione generata deriva da Exception e non è attivo il multithreading con ANTLR.

È stato utile?

Soluzione

Credo di aver capito il problema.L'eccezione viene rilevata, il problema è la confusione sul comportamento del debugger e le differenze nelle impostazioni del debugger tra ogni persona che tenta di riprodurlo.

Nel terzo caso dalla tua riproduzione credo che tu riceva il seguente messaggio:"NoViableAltException non è stata gestita dal codice utente" e uno stack di chiamate simile al seguente:

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

Se fai clic con il pulsante destro del mouse nella finestra dello stack di chiamate ed esegui l'attivazione di mostra codice esterno, vedrai questo:

        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

Il messaggio del debugger ti dice che un'eccezione originata all'esterno del tuo codice (da NoViableAlt) sta attraversando il codice che possiedi in TestAntlr-3.1.exe!TimeDefLexer.mTokens() senza essere gestita.

La formulazione è confusa, ma ciò non significa che l'eccezione non sia stata rilevata.Il debugger ti fa sapere che il codice che possiedi mTokens()" deve essere robusto contro questa eccezione che viene lanciata attraverso di esso.

Cose con cui giocare per vedere come appare per coloro che non hanno riprodotto il problema:

  • Vai agli strumenti/opzioni/debug e disattiva "Abilita solo il mio codice (solo gestito)".o opzione.
  • Vai a Debugger/Eccezioni e disattiva "User-Handled" per le eccezioni di runtime in lingua comune.

Altri suggerimenti

Indipendentemente dal fatto che l'assembly sia stato compilato come build di rilascio, l'eccezione dovrebbe certamente "emergere" al chiamante, non c'è motivo per cui un assembly non compilato in modalità debug dovrebbe avere alcun effetto su ciò.

Sono d'accordo con Daniel nel suggerire che forse l'eccezione si sta verificando su un thread separato: prova ad associare l'evento di eccezione del thread in Application.ThreadException.Questo dovrebbe essere sollevato quando si verifica un'eccezione del thread non gestito.Potresti adattare il tuo codice in questo modo: -

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

Stai utilizzando .Net 1.0 o 1.1?In tal caso, catch(Exception ex) non rileverà le eccezioni dal codice non gestito.Dovrai invece utilizzare catch {}.Vedi questo articolo per ulteriori dettagli:

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

Posso dirti cosa sta succedendo qui...

Visual Studio si interrompe perché ritiene che l'eccezione non sia gestita.Cosa significa non gestito?Bene, in Visual Studio, c'è un'impostazione in Strumenti...Opzioni...Debug in corso...Generale..."Abilita Just My Code (solo gestito)".Se questa opzione è selezionata e se l'eccezione si propaga dal codice e a uno stack frame associato a una chiamata al metodo che esiste in un assembly che è "NON IL TUO CODICE" (ad esempio Antlr), viene considerato "non gestito".Per questo motivo disattivo la funzione Abilita Just My Code.Ma, se me lo chiedi, questo è noioso...diciamo che fai così:

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

doSomething chiama la tua funzione anonima lì e quella funzione genera un'eccezione...

Tieni presente che si tratta di un'"eccezione non gestita" secondo Visual Studio se "Abilita Just My Code" è attivo.Inoltre, tieni presente che si ferma come se fosse un punto di interruzione in modalità debug, ma in un ambiente non di debug o di produzione il codice è perfettamente valido e funziona come previsto.Inoltre, se semplicemente "continui" nel debugger, l'app procede alla grande (non interrompe il thread).È considerata "non gestita" perché l'eccezione si propaga attraverso uno stack frame che NON è nel codice (ad es.nella libreria esterna).Se me lo chiedi, questo è pessimo.Modifica questo comportamento predefinito Microsoft.Questo è un caso perfettamente valido di utilizzo delle eccezioni per controllare la logica del programma.A volte non è possibile modificare la libreria di terze parti in modo che si comporti in altro modo e questo è un modo molto utile per eseguire molte attività.

Prendi MyBatis ad esempio, puoi utilizzare questa tecnica per interrompere l'elaborazione dei record raccolti da una chiamata a SqlMapper.QueryWithRowDelegate.

È possibile che l'eccezione venga lanciata in un altro thread?Ovviamente il tuo codice chiamante è a thread singolo, ma forse la libreria che stai utilizzando sta eseguendo alcune operazioni multithread dietro le quinte.

Sono con @Shaun Austin: prova a racchiudere la prova con il nome completo

catch (System.Exception)

e vedere se questo aiuta. Il documento ANTLR dice quali eccezioni dovrebbero essere lanciate?

Per me, una clausola catch (Exception) avrebbe dovuto catturare qualsiasi eccezione.C'è qualche motivo per cui non dovrebbe?

L'unica possibilità a cui riesco a pensare è che qualcos'altro lo stia rilevando prima di te e lo stia gestendo in un modo che sembra essere un'eccezione non rilevata (ad es.uscire dal processo).

il mio blocco try/catch non lo rileva e interrompe invece l'esecuzione come eccezione non gestita.

È necessario trovare la causa del processo di uscita.Potrebbe trattarsi di qualcosa di diverso da un'eccezione non gestita.Potresti provare a utilizzare il debugger nativo con un punto di interruzione impostato su "{,,kernel32.dll}ExitProcess".Quindi utilizzare sos per determinare quale codice gestito chiama il processo di uscita.

Personalmente non sono affatto convinto della teoria del threading.

L'unica volta che l'ho visto prima, stavo lavorando con una libreria che definiva anche Exception e gli usi che avevo fatto significavano che l'effettivo Catch si riferiva a un diverso tipo di "Exception" (se fosse stato completamente qualificato era Company. Lib.Exception ma non era a causa dell'uso) quindi quando si trattava di catturare un'eccezione normale che veniva lanciata (una sorta di eccezione di argomento se ricordo bene) semplicemente non la rilevava perché il tipo non corrispondeva.

Quindi, in sintesi, esiste un altro tipo di eccezione in uno spazio dei nomi diverso utilizzato in quella classe?

MODIFICARE:Un modo rapido per verificarlo è assicurarsi nella clausola catch di qualificare completamente il tipo di eccezione come "System.Exception" e provarlo!

EDIT2:OK, ho provato il codice e per ora ammetto la sconfitta.Dovrò dargli un'altra occhiata domattina se nessuno ha trovato una soluzione.

Uhm, non capisco il problema.Ho scaricato e provato il tuo file di soluzione di esempio.

Viene generata un'eccezione in TimeDefLexer.cs, riga 852, che viene successivamente gestita dal blocco catch in Program.cs che dice semplicemente Eccezione gestita.

Se rimuovo il commento dal blocco catch sopra di esso, verrà invece inserito quel blocco.

Quale sembra essere il problema qui?

Come ha detto Kibbee, Visual Studio si fermerà sulle eccezioni, ma se gli chiedi di continuare, l'eccezione verrà catturata dal tuo codice.

Ho scaricato il progetto di esempio VS2008 e anche qui sono un po' perplesso.Tuttavia, sono riuscito a superare le eccezioni, anche se probabilmente non in un modo che funzionerà perfettamente per te.Ma ecco cosa ho trovato:

Questo messaggio nella mailing list ho avuto una discussione su quello che sembra essere lo stesso problema che stai riscontrando.

Da lì, ho aggiunto un paio di classi fittizie nel file program.cs principale:

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

e quindi ho aggiunto le righe using in TimeDefParser.cs e TimeDefLexer.cs:

using NoViableAltException = MyNoViableAltException;
using EarlyExitException = NoViableAltException; 

Con ciò le eccezioni si riverserebbero nelle false classi di eccezioni e potrebbero essere gestite lì, ma c'era ancora un'eccezione lanciata nel metodo mTokens in TimeDefLexer.cs.Avvolgendolo in un tentativo di cattura in quella classe è stata rilevata l'eccezione:

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

Davvero non capisco perché racchiuderlo nel metodo interno piuttosto che da dove viene chiamato per gestire l'errore se il threading non è in gioco, ma spero comunque che questo indichi qualcuno più intelligente di me qui nella giusta direzione.

Ho scaricato il tuo codice e tutto funziona come previsto.

Il debugger di Visual Studio intercetta correttamente tutte le eccezioni.I blocchi di cattura funzionano come previsto.

Utilizzo il server Windows 2003 SP2, VS2008 Team Suite (9.0.30729.1 SP)

Ho provato a compilare il tuo progetto per .NET 2.0, 3.0 e 3.5

@Steve Steiner, le opzioni del debugger che hai menzionato non hanno nulla a che fare con questo comportamento.

Ho provato a giocare con queste opzioni senza effetti visibili: i blocchi catch sono riusciti a intercettare tutte le eccezioni.

Steve Steiner ha ragione nel dire che l'eccezione ha origine nella libreria antlr, passa attraverso il metodo mTokens() e viene catturata nella libreria antlr.Il problema è che questo metodo è generato automaticamente da antlr.Pertanto, qualsiasi modifica per gestire l'eccezione in mTokens() verrà sovrascritta quando si generano le classi parser/lexer.

Per impostazione predefinita, antlr registrerà gli errori e tenterà di ripristinare l'analisi.Puoi sovrascriverlo in modo che parser.prog() lanci un'eccezione ogni volta che si verifica un errore.Dal tuo codice di esempio penso che questo sia il comportamento che ti aspettavi.

Aggiungi questo codice al tuo file grammaticale (.g).Dovrai anche disattivare "Abilita Just My Code" nel menu di debug.

@members {

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

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

Questo è il mio tentativo di realizzare una versione C# dell'esempio fornito nel capitolo "Uscire dal riconoscitore al primo errore" del libro "Definitive ANTLR Reference".

Spero che questo sia quello che stavi cercando.

Puoi impostare VS.Net in modo che si interrompa non appena si verifica un'eccezione.Esegui semplicemente il tuo progetto in modalità debug e si fermerà non appena verrà generata l'eccezione.Allora dovresti avere un'idea migliore del motivo per cui non viene catturato.

Inoltre, puoi inserire del codice in catturare tutte le eccezioni non gestite.Leggi il link per maggiori informazioni, ma le basi sono queste due righe.

Application.ThreadException += new ThreadExceptionEventHandler(ThreadExceptionHandler);

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

Oh e in riferimento a ciò che ha detto Kibbee;se selezioni Debug | Eccezioni in VS e fai semplicemente clic su tutte le caselle nella colonna "generata" dovrebbe essere selezionata qualunque cosa AFAIK come "eccezione di prima opportunità", vale a direVS indicherà quando si verifica l'eccezione Di per essere elaborato da tutto il resto e interrompere il codice pertinente.Questo dovrebbe aiutare con il debug.

L'opzione migliore sembra impostare Visual Studio in modo che si interrompa su tutte le eccezioni non gestite (finestra di dialogo Debug -> Eccezioni, seleziona la casella "Eccezioni Common Language Runtime" e possibilmente anche le altre).Quindi esegui il programma in modalità debug.Quando il codice del parser ANTLR genera un'eccezione, dovrebbe essere rilevata da Visual Studio e consentire di vedere dove si verifica, il tipo di eccezione, ecc.

In base alla descrizione, il blocco catch sembra essere corretto, quindi potrebbe verificarsi una delle seguenti cose:

  1. il parser in realtà non lancia un'eccezione
  2. il parser alla fine lancia qualcosa che non deriva da System.Exception
  3. c'è un'eccezione generata su un altro thread che non viene gestito

Sembra che tu abbia potenzialmente escluso il problema n. 3.

Ho analizzato l'assemblaggio esterno con Reflector e non ho trovato alcuna prova di filettatura.

Non riesci a trovare alcun threading non significa che non ci sia threading

.NET ha un "pool di thread" che è un insieme di thread "di riserva" che rimangono per lo più inattivi.Alcuni metodi fanno sì che le cose vengano eseguite in uno dei thread del pool di thread in modo da non bloccare l'app principale.

Gli esempi lampanti sono cose del tipo ThreadPool.QueueUserWorkItem, ma ci sono moltissime altre cose che possono anche eseguire cose nel pool di thread che non sembrano così ovvie, come Delegate.BeginInvoke

Davvero, devi farlo fai quello che suggerisce Kibbee.

hai provato a stampare (Console.WriteLine()) l'eccezione all'interno della clausola catch e non utilizzare Visual Studio ed eseguire l'applicazione sulla console?

Credo che Steve Steiner abbia ragione.Durante la ricerca sui suggerimenti di Steve, mi sono imbattuto questo filo parlando dell'opzione "Abilita Just My Code" in Strumenti|Opzioni|Debugger|Generale.Si suggerisce che il debugger si interrompa in determinate condizioni quando il codice non utente genera o gestisce un'eccezione.Non sono esattamente sicuro del motivo per cui questo sia importante, o perché il debugger affermi specificamente che l'eccezione non è stata gestita quando lo era in realtà.

Sono stato in grado di eliminare le false interruzioni disabilitando l'opzione "Abilita Just My Code".Ciò modifica anche la finestra di dialogo Debug|Eccezioni rimuovendo la colonna "Gestito dall'utente" poiché non è più applicabile.In alternativa, puoi semplicemente deselezionare la casella "Gestito dall'utente" per CLR e ottenere lo stesso risultato.

Grazie mille per l'aiuto a tutti!

"Inoltre, puoi inserire un po 'di codice per catturare tutte le eccezioni non gestite.Leggi il link per maggiori informazioni, ma le basi sono queste due righe ".

Questo è falso.Questo rilevava tutte le eccezioni non gestite in .NET 1.0/1.1 ma era un bug e non era previsto ed è stato risolto in .NET 2.0.

AppDomain.CurrentDomain.UnhandledException 

È concepito solo per essere utilizzato come sala di registrazione dell'ultima possibilità in modo da poter registrare l'eccezione prima che il programma chiuda.Non rileverà l'eccezione dalla versione 2.0 in poi (anche se in .NET 2.0 almeno c'è un valore di configurazione che puoi modificare per farlo funzionare come 1.1 ma non è consigliabile utilizzarlo).

Vale la pena notare che ci sono poche eccezioni tra te non può catch, come StackOverflowException e OutOfMemoryException.Altrimenti, come altre persone hanno suggerito, potrebbe trattarsi di un'eccezione in un thread in background da qualche parte.Inoltre sono abbastanza sicuro che non puoi nemmeno rilevare alcune/tutte le eccezioni non gestite/native.

Non capisco... il tuo blocco catch genera semplicemente una nuova eccezione (con lo stesso messaggio).Ciò significa che la tua dichiarazione di:

Il problema è che in alcuni casi (non tutti) il mio blocco try/catch non lo rileva e interrompe invece l'esecuzione come eccezione non gestita.

è esattamente quello che è previsto accadere.

Sono d'accordo con Daniele Auger E cronoz che questa sembra un'eccezione che ha qualcosa a che fare con i thread.Oltre a ciò, ecco le altre mie domande:

  1. Cosa dice il messaggio di errore completo?Che tipo di eccezione è?
  2. In base all'analisi dello stack che hai fornito qui, l'eccezione non viene lanciata dal tuo codice in TimeDefLexer.mTokens()?

Non sono sicuro di essere poco chiaro, ma in tal caso, vedo che il debugger interrompe l'esecuzione con una "Eccezione non gestita" di tipo NoViableAltException.Inizialmente, non sapevo nulla di questa voce di menu Debug->Eccezioni perché MS si aspetta che tu, al momento dell'installazione di VS, ti impegni su un profilo quando non hai idea di come siano diversi.Apparentemente, Non ero nel profilo dev C# e mi mancava questa opzione.Dopo aver finalmente eseguito il debug di tutte le eccezioni CLR generate, purtroppo non sono riuscito a scoprire alcun nuovo comportamento che possa spiegare il motivo di questo problema di eccezioni non gestite.Tutte le eccezioni generate erano previste e presumibilmente gestite in un blocco try/catch.

Ho esaminato l'assemblaggio esterno e non ci sono prove di multithreading.Con questo intendo che non esiste alcun riferimento a System.Threading e non sono stati utilizzati delegati di sorta.Ho familiarità con ciò che costituisce un'istanza di un thread.Lo verifico osservando la casella degli strumenti Threads al momento dell'eccezione non gestita per visualizzare che esiste un solo thread in esecuzione.

Ho un problema aperto con quelli di ANTLR, quindi forse sono già stati in grado di affrontarlo in passato.Sono stato in grado di replicarlo in un semplice progetto di app console utilizzando .NET 2.0 e 3.5 con VS 2008 e VS 2005.

È solo un punto dolente perché costringe il mio codice a funzionare solo con input del parser valido noto.Utilizzando un IsValid() Il metodo sarebbe rischioso se generasse un'eccezione non gestita in base all'input dell'utente.Manterrò aggiornata questa domanda quando si apprenderà di più su questo problema.

@spoulson,

Se riesci a replicarlo, puoi postarlo da qualche parte?Una strada che potresti provare è utilizzare WinDBG con le estensioni SOS per eseguire l'app e rilevare l'eccezione non gestita.Si interromperà alla prima eccezione (prima che il runtime tenti di trovare un gestore) e in quel punto potrai vedere da dove proviene e quale thread.

Se non hai mai utilizzato WinDBG prima, può essere un po' travolgente, ma ecco un buon tutorial:

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

Una volta avviato WinDBG, puoi attivare/disattivare l'interruzione delle eccezioni non gestite andando su Debug->Filtri eventi.

Wow, quindi delle segnalazioni finora, 2 hanno funzionato correttamente e 1 ha riscontrato il problema che ho segnalato.Quali sono le versioni di Windows, Visual Studio utilizzate e .NET framework con numeri di build?

Utilizzo XP SP2, VS 2008 Team Suite (9.0.30729.1 SP), C# 2008 (91899-270-92311015-60837) e .NET 3.5 SP1.

Se stai utilizzando oggetti com nel tuo progetto e provi a catturare i blocchi e a non catturare le eccezioni, sarà necessario disabilitare Strumenti/Debug/Interruzione quando le eccezioni attraversano AppDomain o l'opzione gestiti/nativi (solo gestiti).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top