visual try tipos sirve qué para lanzar excepciones excepcion errores ejemplos como catch capturar c++ debugging exception-handling stack-overflow structured-exception

try - ¿Cómo puedo garantizar la captura de una excepción estructurada EXCEPTION_STACK_OVERFLOW en C++ en Visual Studio 2005?



try catch finally c# ejemplos (5)

Recuerdo el código de un lugar de trabajo anterior que sonaba similar con controles explícitos de límites en el puntero de pila y lanzando una excepción manualmente.

Ha pasado un tiempo desde que toqué C ++, e incluso cuando lo toqué no sabía lo que estaba haciendo, por lo que advertí al implementador sobre la portabilidad / confiabilidad de dicho consejo.

Fondo

  • Tengo una aplicación con Poof-Crash [ 1 ]. Estoy bastante seguro de que se debe a una pila reventada.
  • La aplicación es Multi-Threaded.
  • Estoy compilando con " Enable C++ Exceptions: Yes With SEH Exceptions (/EHa) ".
  • _set_se_translator() una función de Traductor SE y llamé a _set_se_translator() con ella.
  • He escrito funciones para y configure set_terminate() y set_unexpected() .
  • Para obtener el desbordamiento de pila, debo ejecutarlo en modo de liberación, bajo carga pesada, durante varios días. Ejecutar bajo un depurador no es una opción, ya que la aplicación no puede funcionar lo suficientemente rápido como para lograr el tiempo de ejecución necesario para ver el problema.
  • Puedo simular el problema agregando recursión infinita en la ejecución de una de las funciones, y así probar la captura de la excepción EXCEPTION_STACK_OVERFLOW .
  • Tengo la instalación de WinDBG como el programa de volcado de emergencia y obtengo buena información para todos los demás problemas de bloqueo, pero no esta . El volcado de bloqueo solo contendrá un hilo, que es ''Sleep ()'' ing. Todos los demás hilos han salido.

La pregunta

Ninguna de las cosas que he probado ha resultado en recoger la excepción EXCEPTION_STACK_OVERFLOW .

¿Alguien sabe cómo garantizar la oportunidad de esta excepción durante el tiempo de ejecución en el modo de lanzamiento?

Definiciones

  1. Poof-Crash : la aplicación se bloquea yendo "poof" y desapareciendo sin dejar rastro.

(Teniendo en cuenta el nombre de este sitio, estoy sorprendido de que esta pregunta ya no esté aquí).

Notas

  1. Se publicó una respuesta breve acerca de cómo ajustar el tamaño de la pila para poder forzar el problema más pronto y permitir atraparlo con un depurador. Ese es un pensamiento inteligente, pero desafortunadamente, no creo que sea de ayuda. Es probable que el problema esté causado por un caso de esquina que conduce a una recursión infinita. Acortar la pila no expondría el problema más rápido y probablemente causaría una falla no relacionada en un código validamente profundo. Buena idea, y gracias por publicarla, incluso si la eliminó.

Todo antes de Windows XP no sería (o sería más difícil) generalmente capaz de atrapar desbordamientos de pila. Con la llegada de xp, puede establecer un controlador de excepciones vectorizadas que tenga la oportunidad de desbordar la pila antes de cualquier controlador basado en la pila (excepción estructurada) (esta es la razón por la que los manejadores de excepciones estructuradas están basados ​​en la pila).

Pero realmente no hay mucho que puedas hacer, incluso si eres capaz de atrapar tal excepción.

En su blog , cbrumme (lo siento, no tiene su nombre real) discute una página de pila vecina a la página de guardia (la que genera el desbordamiento de la pila) que potencialmente se puede utilizar para la reversión. Si puede exprimir su código de retroceso para usar solo una página de pila, puede liberar tanto como lo permita su lógica. De lo contrario, la aplicación está prácticamente muerta al encontrarse con el desbordamiento de la pila. La única otra cosa razonable que hacer, después de haberlo atrapado, es escribir un archivo de volcado para una depuración posterior.

Espero eso ayude.


¿Ha considerado ADPlus desde Debugging Tools para Windows?

ADPlus conecta el depurador CDB a un proceso en modo "bloqueo" y generará volcados de emergencia para la mayoría de las excepciones que genera el proceso. Básicamente, ejecuta "ADPlus -crash -p yourPIDhere", realiza una conexión invasiva y comienza a iniciar sesión.

Dado su comentario anterior acerca de ejecutar bajo un depurador, solo quería agregar que CDB agrega prácticamente cero sobrecarga en el modo de bloqueo en una máquina decente (doble núcleo, 2 GB de RAM), así que no dejes que eso te detenga de intentarlo .


No estoy convencido de que estés en el camino correcto al diagnosticar esto como un desbordamiento de pila.

¡Pero en cualquier caso, el hecho de que estás obteniendo un poof! , además de lo que está viendo en WinDbg

El volcado de bloqueo solo contendrá un hilo, que es ''Sleep ()'' ing. Todos los demás hilos han salido.

me sugiere que alguien ha llamado a la función C RTL exit (), o posiblemente a la API de Windows TerminateProcess () directamente. Eso podría tener algo que ver con sus controladores de interrupción o no. Tal vez algo en la lógica de manejo de excepciones tiene una verificación de reingreso y arbitrariamente decide salir () si se vuelve a ingresar.

Mi sugerencia es parchear tus ejecutables para poner quizás una depuración INT 3 en el punto de entrada para exit (), si está enlazado estáticamente, o si está dinámicamente vinculado, parchear la importación y también remendar las importaciones de kernel32 :: TerminateProcess para lanzar un DebugBreak () en su lugar.

Por supuesto, exit () y / o TerminateProcess () también se pueden invocar en un apagado normal, por lo que tendrá que filtrar las falsas alarmas, pero si puede obtener la pila de llamadas para el caso donde está a punto de prueba, deberías tener lo que necesitas.

EDITAR AGREGAR: Simplemente escribir su propia versión de exit () y vincularla en lugar de la versión CRTL podría hacer el truco.


Puede generar símbolos de depuración sin deshabilitar las optimizaciones. De hecho, deberías estar haciendo eso de todos modos. Simplemente hace que la depuración sea más difícil.

Y la documentación para _set_se_translator dice que cada hilo tiene su propio traductor SE. ¿Estás configurando uno para cada hilo?

set_unexpected es probablemente una set_unexpected no set_unexpected , al menos según la documentación de VS 2005. Y cada subproceso también tiene su propio controlador de terminate , por lo que debe instalarlo también por cada subproceso.

También recomendaría NO usar la traducción SE. Toma excepciones de hardware que no debe ignorar (es decir, realmente debe registrar un error y terminar) y las convierte en algo que puede ignorar (excepciones de C ++). Si desea detectar este tipo de error, use un controlador __try/__except .