2009-08-05 12 views
6

He configurado Application.OnException en un controlador de excepciones personalizado para que pueda registrar bloqueos y dar una opción para salir. Sin embargo, ahora descubro que esto se ejecuta incluso con excepciones que ya he manejado, por ejemplo, excepciones que surgen al validar entradas numéricas. ¿Hay alguna manera de que el controlador de excepciones personalizado solo se ejecute en excepciones no controladas?¿Cómo le aviso a Delphi que ya he manejado una excepción?

Editar: resulta que obtengo el comportamiento esperado cuando corro fuera del depurador. Quizás es solo una depuración. No encuentro que la interacción del depurador de Delphi con excepciones sea intuitiva, por decir lo menos.

Respuesta

14

Si el comportamiento cambia dentro y fuera del depurador, entonces realmente no es su programa que le informa sobre las excepciones. He escrito sobre este fenómeno en mi sitio web:

Why do I continue getting error messages even after I have written an exception handler?

un extracto:

En su configuración predeterminada, el IDE de Delphi le notifica cada vez que se produce una excepción en su programa ... Lo que es importante saber es que en ese punto, no del código de manejo de excepciones de su programa se ha ejecutado todavía. Es todo Delphi en sí mismo; su estado especial como depurador le permite obtener la primera notificación de cualquier excepción en su programa, incluso antes de que su programa lo sepa.

Después de cerrar el cuadro de mensaje de Delphi, la ejecución se pausará en la mejor línea del código fuente que Delphi podría encontrar para representar el origen de la excepción. Presione el botón "Ejecutar" para que su programa se reanude. El control pasará al siguiente finalmente o excepto el bloque . Antes de reanudar su programa, puede usar las diversas herramientas de depuración a su disposición. Puede inspeccionar los valores de cualquier variable en el alcance, e incluso puede modificar sus valores.

Entonces, ¿cómo notifica a Delphi que ya ha manejado una excepción?No lo hace, porque su programa aún no lo ha manejado. ¿Y por qué el depurador no puede detectar si su programa es yendo al para manejar una excepción? Porque para hacer eso, necesita ejecutar su programa aún más. Detectar la falta de un manejador de excepciones es como resolver el problema de detención. La única manera de determinar si se va a manejar una excepción es dejar que se ejecute el programa y luego ver si se maneja la excepción. Pero en ese punto, ya es demasiado tarde para realizar cualquier depuración, por lo que el depurador no tiene más remedio que detener su programa cuando detecta una excepción por primera vez y luego, le permite averiguar qué hacer desde allí.

Mi artículo pasa a describir algunas formas en que puede evitar que el retén depurador ciertas excepciones, que se resumen aquí:

  • Uso puntos de interrupción avanzada para desactivar temporalmente rompiendo en excepciones para ciertas regiones del código.
  • configurar el depurador de ignorar ciertas clases de excepciones (y sus descendientes).
  • Informe a todo el depurador no para notificarle acerca de cualquier excepciones.
  • Inhabilita la depuración integrada por completo.

hay otra opciones que no he incluido en mi artículo:

  • cambiar su programa de tal manera que la excepción no consigue creció en el primer lugar.

usted dice que la validación de entrada numérica. A mí me parece que está haciendo algo como llamar al StrToInt y luego atrapar la excepción EConvertError cuando la entrada no es un número entero válido. Esa es una forma costosa de validar la entrada. En lugar de eso, utilice TryStrToInt, que le indicará si la conversión tuvo éxito, o StrToIntDef, que en silencio devolver un valor predeterminado en lugar de lanzar una excepción. Otra opción es simple viejo Val, que intenta convertir una cadena, y si falla, le dice qué posición en la cadena causó la falla. Val es particularmente útil si desea consumir tantos caracteres como sea posible para la conversión y luego reanudar el análisis en el siguiente carácter no numérico.

+0

Guau, gracias por todas las sugerencias. La excepción se maneja cuando se ejecuta a través del depurador, la miro paso a paso por el código de manejo de excepciones, pero luego aparece en el controlador genérico. Examinaré las otras opciones para la conversión de cadenas, eso es realmente lo principal. – Erika

+0

+1 Gran respuesta, Rob. – robsoft

+0

¿Qué hacer si quiero que el depurador no reaccione en un tipo de excepción específico en una rutina específica? No quiero suprimirlos a todos. – Paul

1

Una alternativa podría ser no usar Application.OnException. Pero simplemente capture todas las excepciones en su función "principal". De esta forma, puede capturar todas las excepciones que no haya guardado antes, registrar la excepción y luego bloquear.

+2

Eso es justo lo que el método es para Application.OnException. – jpfollenius

1

Application.OnException solo debe activarse para excepciones no controladas. Reanudar una excepción en un bloque try-except hará que la excepción sea manejada por Application.OnException. Para la validación de entrada que genera una excepción, puede mostrar un mensaje al usuario y luego volver a generar la excepción solo si desea que se registre en el registro de errores.

+0

Lo extraño es que parecía estar volviendo a plantear la excepción sin mi ayuda. Pero cuando edité la pregunta para decir, esto solo ocurre en el depurador. Rareza. Gracias sin embargo. – Erika

4

Citando de la documentación (Delphi 7) en TApplication.OnException

"Use OnException to change the default behavior that occurs when an exception is not 
handled by application code." 

Así: Sólo excepción no controlada estará disponible en el controlador de eventos OnException. Lo que está experimentando es probablemente el Delphi IDE rompiendo la excepción. Esto es (al menos en Delphi 7) configurable.

En Delphi 7 puede configurarlo haciendo clic en el menú Herramientas-> Opciones del depurador. Luego, seleccione "Excepciones de idioma" y desactive la casilla "Detener en excepciones de Delphi". Sin embargo, podría ser diferente en otras versiones delphi.

Cuestiones relacionadas