2011-01-19 27 views
20

Escenario:cómo depurar un StackOverflowException en .NET

He estado en un rollo e implementado un montón de código, pero cuando yo haga lo que se tiran una StackOverflowException? StackOverflowException no tiene stacktrace así que estoy atascado. Sé por qué podría ocurrir un desbordamiento de la pila, pero para solucionarlo necesito saber dónde está la raíz.

Todo lo que estoy haciendo es: Excepción no controlada del tipo 'System.StackOverflowException' producido en la etiqueta-estás-it.dll

Opciones:

  1. escanear a través de toda la cambios y tratar de señalar el problema. (podría ser lento)
  2. Utilice un depurador y siga hasta encontrar el problema. (probablemente mejor que 1.)
  3. Utilice un perfil y busque los métodos más solicitados.
  4. ?

PS:

Ésta es una situación hipotética (aunque no demasiado infrecuente) y por lo tanto no hay código está disponible.

+0

¿Imprime stacktrace? VS tiende a ahogarse cuando se enfrenta con una excepción de stackoverflow. – leppie

+0

El código que causa esto se publica en el enlace en cuestión http://stackoverflow.com/questions/39004357/how-to-fix-stackoverflowexception-in-net – Andrus

Respuesta

12

Esto es casi siempre debido a la recursividad. O bien un método que se llama a sí mismo, o un método que llama a un método que lo devuelve y así sucesivamente.

para encontrarlo:

  • ACTUALIZADO: No me di cuenta, pero al parecer no se puede conseguir el seguimiento de la pila para un StackOverflowException (supongo que algo que ver con no ser capaz de coger uno , ya sea). Sin embargo, hay formas de obtener un volcado as mentioned here.
  • ReSharper mostrará los métodos que se llaman a sí mismos (pone un pequeño círculo verde en la barra lateral para llamadas recursivas) aunque no captará la recursión cuando se trate de dos o más métodos.
  • Utilice una herramienta como ANTS Profiler para ver qué métodos se llaman la mayoría de las veces.
  • Manténgase atento a los eventos que se disparan y que podrían llamar al código, lo que significa que el mismo evento se desencadena nuevamente, lo que provoca un bucle.

De vez en cuando que obtendrá errores tipográficos como esto, también:

private string name; 

public string Name 
{ 
    get { return Name; } // Ooops! This is recursive, all because of a typo... 
} 

que es una razón por la que ahora personalmente prefiero usar propiedades automáticas.

+3

1. No obtiene un stacktrace con una excepción SO. 2. La recursión es probablemente la culpable y el reafilado podría ayudar, pero luego no siempre ayuda a encontrar bucles circulares debido a otros constructos. 3. Un perfil parece una buena opción. – Christo

+0

http://stackoverflow.com/questions/39004357/how-to-fix-stackoverflowexception-in-net/ muestra que esto no es causado por la recursividad. ¿Cómo depurar SOexception en este caso? Esta respuesta supone que esto es causado por la recursión. – Andrus

-1

Encuentra métodos que se autodenominan (o un método llama a otro y viceversa) e inspecciónalos. La recursividad suele ser el principal sospechoso cuando obtienes excepciones de SO.

+1

Sé por qué se producen. El problema es rastrearlos. Solo está indicando la opción 1. – Christo

1

En el método que es el "punto de entrada" a la operación que falla, ponga un punto de interrupción. Explore el código y observe las ocurrencias de la misma secuencia de llamadas a métodos una y otra vez en un patrón idéntico para que la pila de llamadas se haga cada vez más profunda.

Tan pronto como lo note, coloque un punto de interrupción en la ubicación actual, donde sea que esté. Continuar con la ejecución (F5 en Visual Studio): si está en el camino correcto, el depurador se detendrá rápidamente en la misma ubicación y la pila de llamadas será aún más profunda.

Ahora usted tiene un marco de pila "vivo" que puede examinar, con el fin de averiguar cómo garantizar que esta recursión terminará correctamente.

+0

Igual que la sugerencia de Borja. – Christo

+0

Otra forma (ordene las respuestas por 'Oldest') –

+0

;-) Jip, supongo que mi clasificación fue incorrecta. Inicialmente, también voté el tuyo, por si acaso recibí el pedido incorrecto. – Christo

5

Puede ejecutar el programa en modo de depuración y ponerlo en pausa. En la pila de llamadas actual puede ver que hay un método o un grupo de métodos que aparece varias veces, estos son los métodos problemáticos. Ponga un punto de quiebre en este método y mire cómo se llama todo el tiempo.

+0

Es cierto que añadiré paso a paso la depuración como otra opción. – Christo

+0

¡Gracias!Solo toco errores groseros de vez en cuando y no tengo el hábito de usar la Pila de llamadas. Estaba * seguro * de que no tenía un problema de recursión pero, por supuesto, tuve un problema de recursión en una ubicación inesperada y la reparación fue fácil una vez que dejé de intentar intuir qué estaba mal. :-) – clweeks

5

Vaya a Depurar, excepciones y marque la casilla lanzada en 'Excepciones de Common Language Runtime'. Ahora cuando causa la excepción de stackoverflow, el depurador se detendrá (eventualmente) y le mostrará la pila de llamadas.

+2

¿Estás seguro de que funciona en las excepciones de desbordamiento de pila? Son un poco especiales en cómo se manejan. –

+1

Lo hace. Lo he hecho. – Joshua

+2

Quizás valga la pena enfatizar que necesita mirar la ventana Pila de llamadas de Visual Studio no StackTrace de la Excepción que no se configurará (probablemente porque una vez que la pila está llena, no puede hacer nada que requiera más uso de la pila). – Appetere

0

Si tiene el código y puede ejecutar su programa desde Visual Studio, debe romperse en el depurador (si se activan excepciones de primera oportunidad) cuando se encuentra con System.StackOverflowException. Desde allí puede examinar la pila de llamadas y ver qué llamadas están volando la pila. enter image description here

He confirmado que esto funciona para Visual Studio 2010 y Visual C# 2010 Express.

0

Personalmente, me gusta limitarlo tanto como sea posible a una determinada sección de código. Por ejemplo, acabo de tener uno. Lo curioso fue que solo estaba sucediendo en la máquina que no pude depurar directamente.

Tenía dos hilos ejecutándose en paralelo, de modo que dejé uno en ejecución (o podría no tener paralelo).

Pasé luego a través de mis funciones y ha añadido como la impresión a cabo funciones, tales como: Así como función inicia:

Console.WriteLine("<Enter method: {0}", DebuggingHelper.GetCurrentMethod()); 

justo antes del regreso de función:

Console.WriteLine(">Exit method: {0}", DebuggingHelper.GetCurrentMethod()); 

Dónde GetCurrentMethod se define como :

[MethodImpl(MethodImplOptions.NoInlining)] 
public static string GetCurrentMethod() 
{ 
    StackTrace st = new StackTrace(); 
    StackFrame sf = st.GetFrame(1); 
    return sf.GetMethod().Name; 
} 

Luego lo ejecuto, tal vez no agregue a todas las funciones, pero lo suficiente como para restringir dónde está pasando el código. Luego, dentro de esa sección, agrega más.

También puede agregar puntos de control a medida que se ejecuta a través de ciertos métodos.

Luego ejecútelo de nuevo, lo que encontrará es que la excepción StackOverFlow ocurrirá entre esas declaraciones. Sigue estrechándote hasta que lo encuentres.

Bastante simple y rápido para encontrar dónde está pasando de esta manera.

Cuestiones relacionadas