2008-09-20 10 views
13

Después de golpear unas pocas StackOverflowExceptions en .NET noté que omiten por completo los manejadores de excepciones no controlados que .NET ofrece (Application.ThreadException/AppDomain.UnhandledException). Esto es muy preocupante ya que tenemos un código de limpieza crítico en esos manejadores de excepciones.StackOverflowException en .NET

¿Hay alguna manera de superar esto?

Respuesta

18

No realmente; un desbordamiento de pila, o una excepción de memoria insuficiente dentro del CLR en sí significa que algo se ha tornado críticamente incorrecto (generalmente lo obtengo cuando he sido un imbécil y he creado una propiedad recursiva).

Cuando se produce este estado, no hay forma de que el CLR asigne nuevas llamadas a funciones o memoria para permitirle llamar a los manejadores de excepciones; es un escenario "debemos detener ahora".

Sin embargo, si lanza la excepción usted mismo llamará a sus controladores de excepción.

+0

Me resulta algo sorprendente, después de todo el CLR es el código propiedad de Microsoft, podrían haber ahorrado algunos marcos de pila para permitir el manejo de excepciones. – adams

+1

¿Cómo sabría cuánto reservar? En una situación de desbordamiento de la pila, la pila ha crecido a un tamaño tal que no es manejable. Al reservar un espacio, deberá reservar el tamaño máximo de pila, lo que a su vez equivaldría a la mitad de la pila disponible para el software. – blowdart

+2

Ok, entiendo esta idea ... Algo así como ... En un entorno de subproceso único. Pero bueno, podríamos crear más de un hilo, ¿no? Y cada hilo tiene una pila separada, ¿no? Entonces, ¿por qué terminar todo el proceso cuando solo un subproceso se quedó sin pila? –

1

Un stackoverflow no es algo de lo que pueda recuperarse, ya que no puede asignar más memoria de pila incluso para llamar a su manejador de excepciones.

Lo único que realmente puede hacer es rastrear la causa y evitar que ocurra (p.ej. cuidado con la recursión y no asigne grandes objetos en la pila).

25

Existen tres tipos de las llamadas "excepciones asincrónicas". Esa es la excepción ThreadAbortException, la OutOfMemoryException y la StackOverflowException mencionada. Esas excepciones pueden ocurrir en cualquier instrucción en su código.

Y, también hay una manera de superarlos:

La más sencilla es la ThreadAbortException. Cuando el código actual se ejecuta en un bloque final. ThreadAbortExceptions se "mueve" al final del bloque finally. Entonces, todo en un bloque final no puede ser abortado por una ThreadAbortException.

Para evitar una OutOfMemoryException, solo tiene una posibilidad: no asigne nada en el Heap. Esto significa que no tiene permitido crear ningún tipo de referencia nuevo.

Para superar la StackOverflowException, necesita ayuda del Framework. Esta ayuda se manifiesta en regiones de ejecución restringida. La pila requerida se asigna antes de el código real se ejecuta y, además, también garantiza que el código ya está compilado en JIT y, por lo tanto, está disponible para su ejecución.

Hay tres formas de ejecutar código en las Regiones de ejecución constreñidos (copiados de la BCL Team Blog):

  • ExecuteCodeWithGuaranteedCleanup, una forma segura pila desbordamiento de un try/finally.
  • Un bloque try/finally precedido inmediatamente por una llamada a RuntimeHelpers.PrepareConstrainedRegions. El bloque try no está restringido, pero todos los bloqueos catch, finally y fault para ese intento son.
  • Como finalizador crítico: cualquier subclase de CriticalFinalizerObject tiene un finalizador que está ansiosamente preparado antes de asignar una instancia del objeto.
    • Un caso especial es el método ReleaseHandle de SafeHandle, un método virtual que se prepara ansiosamente antes de que se asigne la subclase, y se llama desde el finalizador crítico de SafeHandle.

Puede encontrar más información en estas publicaciones en el blog:

Constrained Execution Regions and other errata [Brian Grunkemeyer] en el blog de BCL equipo.

Joe Duffy's Weblog about Atomicity and asynchronous exception failures donde ofrece una muy buena visión general sobre las excepciones asincrónicas y la solidez en el .NET Framework.

+0

Tenga en cuenta que no todo el espacio de pila necesario si está preasignado, solo algo así como 12 páginas (48K o 96K). Si el código crítico necesita más espacio, fallará y el CER no será de ninguna ayuda. Un CER solo aumenta un poco la garantía de ejecución, no proporciona una garantía del 100%. – Pragmateek

1

blowdart lo clavó, arriba. Dumbass recursivo de propiedad, como le gusta llamarlo. Realmente solo es un problema con escribir el código demasiado rápido.

+0

Usted no está respondiendo la pregunta original .. – nawfal

Cuestiones relacionadas