Excepciones

5. Excepciones

5.1. Sintaxis





Entre el bloque try {} y el catch{} NO VAN SENTENCIAS.

Try

C++ proporciona bloques try para permitir el manejo de excepciones.
Un bloque try consiste en la palabra clave try, seguida de llaves ({}) que definen un bloque de código en el que podrían ocurrir errores. El bloque try encierra instrucciones que podrían ocasionar excepciones, e instrucciones que se deberían omitir si ocurre una excepción.
El control del programa no regresa al punto en el que ocurrió la excepción (conocido como el punto de lanzamiento), debido a que el bloque try ha expirado.
El bloque try SOLO completa su ejecución con éxito si no aparecen excepciones, si hay excepciones se interrumpe.


Catch

Las excepciones se procesan mediante los manejadores catch (también conocidos como manejadores de excepciones), que atrapan y manejan las excepciones.
Por lo menos debe haber un manejador catch inmediatamente después de cada bloque try.

Catch al igual que una función puede recibir distintos argumentos ( etiquetas de excepción ) separados por coma.

Cada manejador catch empieza con la palabra clave catch y especifica entre paréntesis un parámetro de excepción que representa el tipo de excepción que puede procesar el manejador catch. (=> pueden existir varios catch).

Cuando ocurre una excepción en un bloque try, el manejador catch que se ejecuta es aquél cuyo tipo de dato coincide con el tipo de dato de la excepción que ocurrió.

Puesto que los bloques catch se procesan por orden de programa para encontrar un tipo coincidente, un catch(...)  de puntos suspensivos debe ser el último controlador del bloque try asociado. Use catch(...) con precaución; no permita que un programa continúe a menos que el bloque catch sepa cómo controlar la excepción específica detectada. Normalmente, un bloque catch(...) se emplea para registrar errores y realizar limpiezas especiales antes de que se detenga la ejecución de un programa.

catch(...) captura cualquier cosa que haya sido lanzada con throw, ver que aquí NO hay argumento. Dado que en c++ puedes lanzar cualquier cosa, no habría manera de saber qué variable poner ahí, en general no sería bueno usar catch(...), ya que indicaría que es una captura genérica, por lo que no sabemos el por que de la excepción.

Por lo general, un manejador catch reporta el error al usuario, lo registra en un archivo, termina el programa sin que haya pérdida de datos o intenta una estrategia alterna para realizar la tarea fallida, por ejemplo pedir un reingreso.

Si ocurre una excepción como resultado de una instrucción en un bloque try, este bloque expira (es decir, termina de inmediato). A continuación, el programa busca el primer manejador catch que pueda procesar el tipo de excepción que ocurrió. El programa localiza el catch que coincida, comparando el tipo de la excepción lanzada con el tipo del parámetro de excepción de cada catch, hasta que el programa encuentra una coincidencia.

Regla relacionada con try/catch:
Si NO escribimos una sección de captura que corresponda a determinado tipo de excepción, esta excepción no se capturará en el caso de que se produzca, y seguirá su destructivo trayecto por la pila de ejecución de la aplicación, por este motivo se podría usar catch(...).

Throw

La instrucción throw, que significa “lanzar”. Esta instrucción interrumpe la ejecución del programa y provoca la terminación de todas las funciones pendientes, a menos que se tomen medidas especiales.
Al ejecutar la excepción hay que asociarle un valor que porte la información acerca de la situación que la ha provocado.
Un ejemplo típico de instrucción para elevar una excepción es el siguiente:

throw atencion("¡Algo va mal!");

En esta línea el comando throw crea una clase llamada "atención" en tiempo de ejecución, con el argumento de constructor; "¡Algo va mal!". El mensaje se almacena en la propiedad Message del objeto de excepción construido.

Hay un detalle importante: la ejecución de throw va interrumpiendo una a una cada función pendiente en la pila de la aplicación y va destruyendo las variables locales.

El código después de la cláusula try es la sección de código protegida, la expresión throw inicia (es decir, produce) una excepción, así que throw es la que lanza una excepción.

El operando de una instrucción throw puede ser de cualquier tipo. Si el operando es un objeto (un objeto es la instancia de una clase ) lo llamamos objeto excepción; pero también puede ser un operando, como el valor de una expresión ( por ejemplo, throw x > 0) o el valor de un int ( por ejemplo, throw -1).

Captura todas las excepciones en C++

El nuevo mecanismo de excepción actual es una forma de capturar todas las excepciones en C++; se introdujo en C++11.  Es una alternativa a la técnica antigua de capturar solo algunas excepciones con bloques try-catch.

Forma antigua:

La forma antigua era usar la palabra clave throw para lanzar una excepción y atraparla con un bloque try-catch

Forma nueva:

La nueva forma es usar la palabra clave throw seguida de una lista de tipos de excepciones que queremos capturar.

Nota del Docente:
Para los casos sencillos que veamos, es probable que no se perciban o existan las diferencias entre la forma nueva y la vieja.

Pasos para capturar todas las excepciones en C++

Se necesitan los siguientes pasos para detectar todas las excepciones en C++:
  1. Declare una clase que se usará como controlador de excepciones.
  2. Defina qué excepciones debe capturar este controlador.
  3. Haga que la función principal llame al nuevo mecanismo de excepción de C++ 11 con una instancia de la clase utilizada para detectar excepciones.
  4. Escriba el código que puede generar una excepción y asegúrese de que el mecanismo de excepción actual lo atrape.
El nuevo mecanismo de excepción de C++11 facilita que los programadores se aseguren de detectar todos los posibles errores de tiempo de ejecución en su código sin tener que escribir manualmente bloques try-catch para cada uno de ellos.

Error del tipo Segmentatio fault:

Segmentation fault NO es una excepción !!.Los errores como las fallas de segmentación son de nivel inferior y try-catch ignora estos eventos y se comporta igual que si no hubiera un bloque try-catch. Se define como violación de acceso (violación del segmento o access violation y segmentation fault en Inglés) al intento fallido de acceso a información o a programas a los que no se tiene autorización para ver o modificar

https://www.delftstack.com/es/howto/cpp/cpp-catch-all-exceptions/#escriba-el-c%C3%B3digo-que-puede-generar-una-excepci%C3%B3n-y-aseg%C3%BArese-de-que-el-mecanismo-de-excepci%C3%B3n-actual-lo-atrape