handling - StackOverflowException en.NET
exception c# example (4)
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.
private Thing _myThing = null;
Public Thing MyThing
{
get{
return this.MyThing;}
set{
this.MyThing = value;}
}
Después de golpear algunos 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.
¿Hay alguna forma de superar esto?
Hay tres tipos de llamadas "excepciones asincrónicas". Esa es la excepción ThreadAbortException, la OutOfMemoryException y la Exception mencionada. Esas excepciones pueden ocurrir en cualquier instrucción en su código.
Y, también hay una manera de superarlos:
La más fácil 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 excepción 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 Exception, necesita ayuda del Framework. Esta ayuda se manifiesta en regiones de ejecución restringida. La pila requerida se asigna antes de que se ejecute el código real y, además, también asegura 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 regiones de ejecución restringida (copiadas del blog del equipo BCL ):
- ExecuteCodeWithGuaranteedCleanup, una forma segura de desbordamiento de pila 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 preparado con entusiasmo antes de que se asigne 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 en estas publicaciones de blog:
Regiones de ejecución restringida y otras erratas [Brian Grunkemeyer] en el Blog del equipo BCL.
El Weblog de Joe Duffy sobre Atomicity y fallas de excepción asíncronas ofrece una muy buena visión general sobre las excepciones asincrónicas y la solidez en el .NET Framework.
Realmente no; 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 de "debemos detenernos ahora ".
Sin embargo, si lanza la excepción usted mismo será llamado a sus manejadores de excepciones.
Un 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 puede hacer es rastrear la causa y evitar que ocurra (p.ej. cuidado con la recursión y no asignar objetos grandes en la pila).