2011-09-20 11 views
5

Se scrivo questo:Perché .NET non registra la traccia dello stack per le eccezioni StackOverflow?

class Program 
{ 
    static void Main(string[] args) 
    { 
     throw new Exception("lol"); 
    } 
} 

e eseguire il file EXE dalla riga di comando, ottengo due voci nel mio registro eventi. Uno è un errore dell'applicazione che dice che c'era un'eccezione non gestita, e l'altro contiene la traccia dello stack con il sorgente come. NET Runtime.

Se scrivo questo:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Recurse4Evr(); 
    } 

    static void Recurse4Evr() 
    { 
     Recurse4Evr(); 
    } 
} 

Ho solo una voce nel mio registro eventi, che dice errore di applicazione e che non c'era un'eccezione di overflow dello stack. Non c'è quella seconda voce con la traccia dello stack, quindi è fondamentalmente inutile.

Perché non viene registrata anche la traccia dello stack? Se imposto DebugDiag e lo allego al mio processo e poi c'è un overflow dello stack, DebugDiag è in grado di registrare la traccia dello stack. Ovviamente la traccia dello stack è in qualche modo disponibile per il mondo esterno. Se il runtime sta terminando il processo perché ha rilevato uno stackoverflow, allora sa anche qual è lo stack.

Nelle applicazioni di grandi dimensioni che presentano molte interazioni complesse, spesso non è possibile ricreare le condizioni che hanno causato un overflow dello stack. In questa situazione, una traccia di stack è l'unico modo per capire cosa è successo. Perché Microsoft decise che non era importante registrare queste informazioni? C'è stata una decisione di design legittima che non è ovvia?

+4

La mia ipotesi sarebbe che la generazione dello stack in-process richiede chiamate di funzione, che non possono funzionare perché lo stack è in overflow. Il debugger aggira il problema essendo in grado di camminare nello stack usando le proprie strutture dati e (si spera) una pila sana. – siride

+0

Questa è una bella domanda! Mi chiedo se abbia a che fare con il modo in cui vengono rilevati gli overflow dello stack ... Dopo .Net 2.0, sembra che anche tu non riesca a prenderlo, quindi sembra che funzioni da una serie speciale di regole. –

+0

possibile duplicato di [C# cattura un'eccezione di overflow dello stack] (http://stackoverflow.com/questions/1599219/c-catch-a-stack-overflow-exception) – balexandre

risposta

0

Questo è apparentemente impossibile. Se si desidera una traccia dello stack in modo da poter trovare il codice incriminato che ha ucciso l'applicazione, è necessario allegare uno strumento di terze parti come DebugDiag o AdsPlus. Buona fortuna, non c'è praticamente nessuna documentazione per questi strumenti.

1

L'overflow dello stack è considerato una situazione non recuperabile e per tale il tempo di esecuzione uccide il processo.

per riassumere:

from Damien_The_Unbeliever

Dalla pagina MSDN StackOverflowException s:

Nelle versioni precedenti del .NET Framework, l'applicazione potrebbe prendere un oggetto StackOverflowException (ad esempio, per recuperare dalla ricorsione illimitata). Tuttavia, tale pratica è attualmente scoraggiata perché è necessario un codice aggiuntivo significativo per intercettare in modo affidabile un'eccezione di overflow dello stack e continuare l'esecuzione del programma.

A partire da .NET Framework versione 2.0, un oggetto StackOverflowException non può essere rilevato da un blocco try-catch e il processo corrispondente viene terminato per impostazione predefinita. Di conseguenza, si consiglia agli utenti di scrivere il loro codice per rilevare e prevenire un overflow dello stack. Ad esempio, se l'applicazione dipende dalla ricorsione, utilizzare un contatore o una condizione di stato per terminare il ciclo ricorsivo. Si noti che un'applicazione che ospita Common Language Runtime (CLR) può specificare che il CLR scarica il dominio dell'applicazione in cui si verifica l'eccezione di overflow dello stack e lascia che il processo corrispondente continui. Per ulteriori informazioni, vedere ICLRPolicyManager Interface e Hosting Common Language Runtime.


from JaredPar

Partendo da 2.0 un'eccezione StackOverflow possono essere catturati soltanto nelle seguenti circostanze.

  1. Il CLR viene eseguito in un ambiente ospitato in cui l'host consente specificamente per le eccezioni StackOverflow ad essere gestite
  2. L'eccezione StackOverflow viene lanciata dal codice utente e non a causa di una situazione reale di overflow dello stack (Reference)
+0

non sto provando a prenderlo. ti sto chiedendo il motivo per cui quando il tuo programma termina e il runtime registra che c'era un errore nel registro eventi, perché non include la traccia dello stack. – dan

+0

Inoltre, penso che il "consiglio" di Microsoft sia molto semplicistico. certo, ha senso per gli algoritmi ricorsivi - ovviamente dovresti scrivere fibonacci nel modo iterativo. il mio caso non era un algoritmo ricorsivo, c'era un errore nel logger nel mio gestore di eventi di eccezione. il logger ha gettato, e poi il gestore eventi è stato attivato di nuovo, ha lanciato di nuovo, ecc. Sono stato in grado di trovare solo ciò che ha causato l'overflow usando DebugDiag. il consiglio di microsoft è fondamentalmente "non scrivere codice che abbia bug". – dan

Problemi correlati