C# captura una excepción de desbordamiento de pila


Recibí una llamada recursiva a un método que lanza una excepción de desbordamiento de pila. La primera llamada está rodeada por un bloque try catch, pero la excepción no está atrapada.

¿La excepción de desbordamiento de pila se comporta de una manera especial ? ¿Puedo detectar / manejar correctamente la excepción ?

NB: si procede:

  • La excepción no se lanza en el hilo principal

  • El objeto donde el código está lanzando la excepción es cargado manualmente por Asamblea.LoadFrom(...).CreateInstance(...)

Author: Ether, 2009-10-21

9 answers

A partir de la versión 2.0, una excepción de StackOverflow solo se puede detectar en las siguientes circunstancias.

  1. El CLR se está ejecutando en un entorno alojado donde el host permite específicamente que se manejen las excepciones de StackOverflow
  2. La excepción stackoverflow es lanzada por el código de usuario y no debido a una situación real de desbordamiento de pila (Referencia)
 91
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-21 07:20:08

La forma correcta es arreglar el desbordamiento, pero....

Puedes darte una pila más grande: -

using System.Threading;
Thread T = new Thread(threadDelegate, stackSizeInBytes);
T.Start();

Puede usar el Sistema.Diagnostico.StackTrace FrameCount propiedad para contar los fotogramas que ha utilizado y lanzar su propia excepción cuando se alcanza un límite de fotogramas.

O bien, puede calcular el tamaño de la pila restante y lanzar su propia excepción cuando cae por debajo de un umbral: -

class Program
{
    static int n;
    static int topOfStack;
    const int stackSize = 1000000; // Default?

    // The func is 76 bytes, but we need space to unwind the exception.
    const int spaceRequired = 18*1024; 

    unsafe static void Main(string[] args)
    {
        int var;
        topOfStack = (int)&var;

        n=0;
        recurse();
    }

    unsafe static void recurse()
    {
        int remaining;
        remaining = stackSize - (topOfStack - (int)&remaining);
        if (remaining < spaceRequired)
            throw new Exception("Cheese");
        n++;
        recurse();
    }
}

Solo atrapa el Queso. ;)

 42
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-21 11:33:21

Desde la página de MSDN en StackOverflowException s:

En versiones anteriores de. NET Marco, su aplicación podría capturar un objeto StackOverflowException (por ejemplo, para recuperarse de recursión ilimitada). Sin embargo, que la práctica se desaconseja actualmente debido a que el código adicional significativo es necesario para atrapar una pila de forma fiable excepción de desbordamiento y continuar ejecución del programa.

Comenzando con. NET Framework versión 2.0, a StackOverflowException el objeto no puede ser capturado por un intento de captura bloque y el proceso correspondiente es terminado por defecto. Consecuentemente, se aconseja a los usuarios escribir su código para detectar y prevenir una pila desbordamiento. Por ejemplo, si su la aplicación depende de la recursión, el uso un contador o una condición de estado para termina el bucle recursivo. Nota que una aplicación que aloja el common language runtime (CLR) puede especifique que el CLR descarga el dominio de aplicación donde pila se produce una excepción de desbordamiento y el proceso correspondiente continúa. Para más información, ver ICLRPolicyManager Interfaz y Alojamiento del Tiempo de ejecución del Lenguaje Común.

 35
Author: Damien_The_Unbeliever,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-21 07:19:08

Como ya han dicho varios usuarios, no puedes atrapar la excepción. Sin embargo, si tiene dificultades para averiguar dónde está sucediendo, es posible que desee configurar visual Studio para que se rompa cuando se lance.

Para hacer eso, debe abrir la Configuración de excepciones desde el menú 'Debug'. En versiones anteriores de Visual Studio, esto está en 'Debug' - 'Exceptions'; en versiones más recientes, está en' Debug ' - 'Windows' - 'Exception Settings'.

Una vez que tenga la configuración abierta, expanda ' Common Language Excepciones en tiempo de ejecución', expanda 'Sistema', desplácese hacia abajo y marque ' Sistema.StackOverflowException". Luego puede mirar la pila de llamadas y buscar el patrón de repetición de llamadas. Eso debería darte una idea de dónde buscar para arreglar el código que está causando el desbordamiento de la pila.

 20
Author: Simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-24 09:20:22

Como se mencionó anteriormente varias veces, no es posible capturar una excepción de StackOverflowException que fue planteada por el Sistema debido a un estado de proceso dañado. Pero hay una manera de notar la excepción como un evento:

Http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

A partir de la versión 4 de. NET Framework, este evento no se genera para excepciones que dañan el estado del proceso, como desbordamientos de pila o violaciones de acceso, a menos que el controlador de eventos es crítico para la seguridad y tiene el atributo HandleProcessCorruptedStateExceptionsAttribute.

Sin embargo, su aplicación terminará después de salir de la función de eventos (una solución MUY sucia, era reiniciar la aplicación dentro de este evento jaja, no lo he hecho y nunca lo haré). Pero es lo suficientemente bueno para la tala!

En las versiones 1.0 y 1.1 de. NET Framework, una excepción no controlada que ocurre en un subproceso distinto del subproceso principal de la aplicación es atrapado por el tiempo de ejecución y, por lo tanto, no causa que la aplicación finalice. Por lo tanto, es posible que el evento UnhandledException se genere sin que la aplicación termine. A partir de la versión 2.0 de.NET Framework, se eliminó este respaldo para excepciones no controladas en subprocesos secundarios, porque el efecto acumulativo de tales fallos silenciosos incluía degradación del rendimiento, datos dañados y bloqueos, todos los cuales eran difíciles de depurar. Para más información, incluyendo una lista de casos en los que el tiempo de ejecución no termina, consulte Excepciones en Subprocesos administrados.

 11
Author: FooBarTheLittle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-28 09:33:27

Sí desde CLR 2.0 el desbordamiento de pila se considera una situación no recuperable. Así que el tiempo de ejecución aún cierra el proceso.

Para más detalles, consulte la documentación http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx

 6
Author: Brian Rasmussen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-21 07:18:50

No puedes. El CLR no te dejará. Un desbordamiento de pila es un error fatal y no se puede recuperar.

 5
Author: Matthew Scharley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-21 07:19:35

No se puede como la mayoría de los mensajes están explicando, permítanme añadir otra área:

En muchos sitios web encontrará personas que dicen que la forma de evitar esto es usar un dominio de aplicación diferente, por lo que si esto sucede, el dominio se descargará. Eso es absolutamente incorrecto (a menos que aloje su CLR) ya que el comportamiento predeterminado del CLR generará un evento KillProcess, derribando su AppDomain predeterminado.

 5
Author: No hay Problema,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-11 08:39:26

Es imposible, y por una buena razón (por un lado, piense en todas las capturas(Excepción){} alrededor).

Si desea continuar la ejecución después del desbordamiento de pila, ejecute código peligroso en un dominio de aplicación diferente. Las directivas CLR se pueden configurar para terminar el dominio de aplicación actual en caso de desbordamiento sin afectar al dominio original.

 3
Author: ima,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-21 08:17:31