2012-05-21 21 views
7

Estoy refabricando un código antiguo, y una de las cosas que me gustaría abordar es la forma en que se manejan los errores. Soy consciente de las excepciones y de cómo funcionan, pero no estoy del todo seguro de que sean la mejor solución para las situaciones que trato de manejar.¿Cómo finalizar un programa en C++ después de un error?

En este código, si las cosas no se validan, realmente no hay ninguna razón o ventaja para desenrollar la pila. Hemos terminado. No tiene sentido tratar de salvar el barco, porque es un código no interactivo que se ejecuta en paralelo a través del motor Sun Grid. El usuario no puede intervenir. Además, estas fallas de validación en realidad no representan circunstancias excepcionales. Ellos son esperados.

Entonces, ¿cómo puedo tratar mejor con esto? Una cosa que no estoy seguro de querer es un punto de salida en cada método de clase que puede fallar. Eso parece imposible de mantener. ¿Me equivoco? ¿Es una práctica aceptable simplemente llamar al exit() o al abort() en el punto de falla en códigos como este? ¿O debería lanzar una excepción de regreso a alguna declaración de captura genérica en main? ¿Cuál es la ventaja?

+0

¿Hay algún problema con la recuperación de una excepción o simplemente desea salir cada vez que ocurre un error? ¿No es demasiado cuando su aplicación falla cada vez que ocurre un error? – DumbCoder

+0

Estoy usando excepciones y similares para problemas no fatales. Estoy tratando de abordar la situación de error fatal aquí. – Fadecomic

Respuesta

4

Lanzar una excepción para ser capturado en main y luego salir significa que los objetos de recursos de RAII se limpian. En la mayoría de los sistemas, esto no es necesario para muchos tipos de recursos. El sistema operativo limpiará la memoria, los identificadores de archivos, etc.(aunque utilicé un sistema en el que no se liberaba la memoria significaba que permanecía asignado hasta que el sistema se reiniciara, por lo que la pérdida de la salida del programa no era una buena idea.)

Pero hay otros tipos de recursos que es posible que desee liberar limpiamente, como conexiones de red o de base de datos, o un dispositivo mecánico que está manejando y necesita cerrar de manera segura. Si una aplicación usa muchas de estas cosas, es posible que prefiera lanzar una excepción para volver a desenrollar la pila y luego salir.

Así que el método apropiado de salir depende de la aplicación. Si una aplicación sabe que es seguro, llamar a _Exit(), abort(), exit() o quickexit() puede ser perfectamente razonable. (El código de la biblioteca no debe llamar a estos, ya que obviamente la biblioteca no tiene idea de si es seguro para cada aplicación que alguna vez usará la biblioteca). Si hay alguna limpieza crítica que debe realizarse antes de que una aplicación salga, pero usted sabe que es limitada , entonces la aplicación puede registrar ese código de limpieza a través de atexit() o at_quick_exit().

Así que, básicamente, decida lo que necesita limpiar, documente, impleméntelo e intente asegurarse de que se haya probado.

2

yo sugeriría que llamar a la función global

void stopProgram() { 
    exit(1); 
} 

Más tarde se puede cambiar su comportamiento, por lo que es fácil de mantener.

+0

Es 'void exit (int status)', no 'void exit()'. – Griwes

+0

@Griwes: Gracias, actualizado –

1

Como usted señaló, tener un exit o abort arrojado por todo su código no es mantenible ... además, puede haber un mecanismo en el futuro que podría permitirle recuperarse de un error, o manejar un error en de una manera más elegante que simplemente salir, y si ya ha codificado esta funcionalidad, sería muy difícil de deshacer.

Lanzar una excepción atrapada en main() es su mejor apuesta en este punto que también le dará flexibilidad en el futuro si ejecuta el código en un escenario diferente que le permitirá recuperarse de errores o manejarlos diferentemente. Además, lanzar excepciones podría ayudar si decide agregar más soporte de depuración, etc., ya que le dará puntos para implementar funciones de registro y registrar el estado del programa desde puntos aislados y mantenibles en el software antes de decidir dejar salir el programa.

4

Es aceptable finalizar el programa si no puede manejar el error correctamente. Hay algunas cosas que puede hacer:

  • Llame al abort() si necesita un volcado del núcleo.
  • Llame al exit() si desea dar la oportunidad de ejecutar aquellas rutinas registradas con atexit() (que es más probable que llame a destructores para objetos globales de C++).
  • Llame al _exit() para finalizar un proceso de inmediato.

No hay nada de malo con el uso de esas funciones, siempre que comprenda lo que está haciendo, conozca sus otras opciones y elija esa ruta de buen grado. Después de todo, es por eso que esas funciones existen. Entonces, si no cree que tenga sentido tratar de manejar el error o hacer cualquier otra cosa cuando sucede, adelante. Lo que probablemente haría es intentar registrar algún mensaje informativo (por ejemplo, para syslog) y llamar al _exit. Si el registro falla, llame al abort para obtener un núcleo a lo largo de la terminación.

Cuestiones relacionadas