2013-03-11 6 views
14

Ogni volta che un test dell'unità fallisce a causa di un StackOverflowException, il processo di test unitario termina immediatamente - l'unico modo per scoprire cosa è successo (di cui sono a conoscenza) è eseguire il debug di un crash dump del processo di test di unità ottenuto seguendo la procedura trovati quiTest di debug dell'unità falliti a causa di un'eccezione StackOverflow

Qual è il modo più semplice di ottenere il nome del test di unità che era in esecuzione al momento in cui il StackOverflowException fu gettato? Anche quando eseguo il debug del test delle unità, sto cercando di trovare il nome del test unitario corrente in fondo allo stack e Visual Studio non ha mostrato l'intero stack nella finestra di debug perché è troppo grande.

C'è un modo per scoprire quale test dell'unità è fallito senza raccogliere e debuggare i crash dump?

+0

Non sono sicuro di cosa stia troncando l'eccezione. Potresti provare a creare il tuo stacktrace proprio con 'new System.Diagnostics.StackTrace (true)' nell'orologio e/o nella finestra intermedia? Forse questo ti fornirà una traccia completa. – Caramiriel

+1

@Caramiriel Esecuzione che mentre esegue il debug in modo interattivo restituisce "Impossibile valutare l'espressione perché il thread corrente è in uno stato di overflow dello stack", non è possibile eseguire espressioni immediate durante il debug di un dump di arresto anomalo poiché il processo non è effettivamente in esecuzione in quel punto. L'intera traccia dello stack non viene mostrata perché è enorme. – Justin

+0

@Justin: Se la tua architettura di Visual Studio (ad esempio x86) corrisponde alle tue applicazioni, puoi anche caricare SOS e scaricare lo stacktrace digitando '! Clrstack' nella finestra immediata. Sembra funzionare per me. ('0028ed6c 00340147 ConsoleApplication45.Program.Rec() 0028edac 003400fb ConsoleApplication45.Program.Main (System.String [])') – Caramiriel

risposta

1

Come menzionato in this other question, non è possibile rilevare un'eccezione di overflow dello stack a meno che non venga lanciata da soli.

Quindi, come soluzione al problema (non proprio una soluzione) è possibile inserire una chiamata di metodo nel codice per rilevare un sovraccarico di stack, quindi lanciare l'eccezione manualmente e recuperarla in un secondo momento.

[TestClass] 
public class TestStackOverflowDetection 
{ 
    [TestMethod] 
    public void TestDetectStackOverflow() 
    { 
     try 
     { 
      InfiniteRecursion(); 
     } 
     catch (StackOverflowException e) 
     { 
      Debug.WriteLine(e); 
     } 
    } 

    private static int InfiniteRecursion(int i = 0) 
    { 
     // Insert the following call in all methods that 
     // we suspect could be part of an infinite recursion 
     CheckForStackOverflow(); 

     // Force an infinite recursion 
     var j = InfiniteRecursion(i) + 1; 
     return j; 
    } 

    private static void CheckForStackOverflow() 
    { 
     var stack = new System.Diagnostics.StackTrace(true); 
     if (stack.FrameCount > 1000) // Set stack limit to 1,000 calls 
     { 
      // Output last 10 frames in the stack 
      foreach (var f in stack.GetFrames().Reverse().Take(30).Reverse()) 
       Debug.Write("\tat " + f); 

      // Throw a stack overflow exception 
      throw new StackOverflowException(); 
     } 
    }