2010-08-26 17 views
10

No necesito una lección para pasar de los medios recursivos a los no recursivos, solo quiero saber por qué no podemos tratar este tipo de excepción. De todos modos, estoy usando funciones recursivas en listas muy grandes.C# - ¿Cómo maneja/captura StackOverFlowExceptions?

He escrito código para intentar coger StackOverFlowExceptions:

try { recursiveFxn(100000); } 
catch(Exception){}
private void recursiveFxn(int countdown) 
{ 
if (countdown > 0) 
    recursiveFxn(countdown - 1); 
else 
    throw new Exception("lol. Forced exception."); 
}

Pero aún así me sale errores en el programa (tanto en NUnit y una página web que estoy corriendo). ¿Por qué no se captura la excepción?

+0

me sorprende que exista esta excepción ... fuera del código administrado, no estoy seguro de que sea posible recuperar este error en general. –

+0

@RobertKarl: Ojalá hubiese un medio a través del cual el código pudiera verificar explícitamente la pila para una cierta cantidad de espacio, con una excepción lanzada si el espacio no estaba disponible. Si dicho método arrojó la excepción antes de que la pila se desbordara, y si la cantidad de espacio solicitado era al menos igual a la suma del máximo de la pila que se asignará entre las pruebas, más la cantidad requerida para el código de recuperación, tales excepciones podrían ser 100% recuperable. Tal como están las cosas, no sé cómo escribir código recursivo seguro que no limite artificialmente la profundidad de las estructuras que puede manejar. – supercat

Respuesta

16

Dado que .NET Framework 2.0, StackOverflowException no se puede atrapar. Esto se debe a que se considera una mala práctica. Citando la MSDN documentation:

Comenzando con el .NET Framework versión 2.0, un objeto StackOverflowException no puede ser atrapado por un bloque try-catch y el proceso correspondiente es terminado por defecto. En consecuencia, se recomienda a los usuarios de escribir su código para detectar y evitar un desbordamiento de la pila . Por ejemplo, si su aplicación depende de la recursión, use un contador o una condición de estado en finalice el ciclo recursivo.

Ahora, la única manera de coger un StackOverflowException es cuando fue lanzada por el código de usuario, tal como se explica en un blog by Jared Parsons. Aparte de eso, por hosting the CLR, puede manejar (pero no capturar) un StackOverflowException e idear una forma de permitir que la ejecución de su programa continúe.

Tenga en cuenta que debido a que la pila se desenrolla cuando se produce una excepción, en pre-2.0 versiones de .Net la pila en realidad sería mucho más corto cuando se manipula el StackOverflowException, por lo que es posible hacerlo sin generar otro StackOverflowException.

+0

Excelente respuesta, gracias. – user420667

-1

No se puede detectar una excepción de desbordamiento de pila porque cuando sucede mata el hilo muerto. Try ... catch ... se realiza con el mismo hilo, por lo que no funcionará. Puede haber algunas API de nivel inferior que podría P/Invocar y tener otro hilo atraparlo. También puede haber algunas API de nivel inferior para cambiar el tamaño máximo de la pila, pero no veo nada en .NET Framework para ayudar con eso, así que de nuevo necesitaría P/Invocar algo.

+0

-1 porque como menciono anteriormente, las excepciones de desbordamiento de pila podrían quedar atrapadas en versiones anteriores de .Net, por lo que su respuesta de que "no funcionará porque está en el mismo subproceso" es incorrecta. – Virtlink

+0

@Virtlink: Si recuerdo correctamente, en .net 1.0, si intenté capturar 'StackOverflowException'," generalmente "funcionaría.Hubo una sobrecarga sustancial, sin embargo, para permitir que tales excepciones "usualmente" se captaran antes de que el contexto del hilo se dañase sin posibilidad de reparación, y a pesar de tal sobrecarga la característica no era lo suficientemente confiable como para ser útil. En .NET 2.0, Microsoft decidió que era mejor exigir que los programadores usen algún otro medio de recuperación a partir de tales condiciones, que incurrir en gastos generales por lo que podrían tratar de utilizar un enfoque de recuperación que, de todos modos, podría no funcionar. – supercat