Las excepciones son situaciones anómalas que requieren un tratamiento especial. ¡¡No tienen por qué ser errores!! Si se consigue dominar su programación, la calidad de las aplicaciones que se desarrollen aumentará considerablemente. El funcionamiento general del mecanismo de lanzamiento y tratamiento de excepciones es el siguiente: • Existe un método que invoca la ejecución de otro. • Este método más interno se encuentra en una situación que puede considerarse como excepcional. Por lo tanto lanza una excepción. • En este momento termina la ejecución del método más interno y se retorna inmediatamente al método llamador. • El método llamador debe capturar la excepción y la trata. Parte del tratamiento de la excepción puede ser volver a lanzarla al método que invocó a este. La correcta programación de excepciones significa diseñar los algoritmos pensando únicamente en la forma habitual en la que deben ejecutarse, manejando las situaciones extraordinarias a parte. De esta manera se consigue un diseño mucho más estructurado, legible, robusto y fácil de mantener.

Ejemplo. Cuando solicitamos memoria al sistema, lo habitual es que exista suficiente memoria disponible y no haya ningún problema. Pero si queremos realizar una aplicación robusta deberemos de tener en cuenta la eventualidad de que dicha memoria no se conceda, lo cual complica enormemente un sencillo algoritmo. Veamos una función escrita en C que simplemente intenta asignar memoria dinámica para tres enteros: void Sin Excepciones? (void) {

   int *p1, *p2, *p3;

   p1 = (int*) malloc(sizeof(int));

   if (p1 == NULL) {
      printf(“No hay suficiente memoria”);
      abort();
   }

   p2 = (int*) malloc(sizeof(int));

   if (p2 == NULL) {
      printf(“No hay suficiente memoria”);
      abort();
   }

   p3 = (int*) malloc(sizeof(int));

   if (p3 == NULL) {
      printf(“No hay suficiente memoria”);
      abort();
   }

} Si programamos en C++ y hacemos uso de las excepciones: void Con Excepciones? (void) {

   int *p1, *p2, *p3;

   try {
      p1 = new int; // Comportamiento normal.
      p2 = new int;
      p3 = new int;
   }

   catch(…){  // Comportamiento excepcional.

      printf(“No hay suficiente memoria”);
      abort();
   }

} El ANSI C++ especifica que si una instrucción new falla (no hay memoria disponible) debe lanzar la excepción bad_alloc (definida en el fichero de cabecera new). Las instrucciones que pueden provocar el lanzamiento de una excepción (la “zona crítica”) se encierran en un bloque try. Si alguna de las instrucciones del bloque try provocara una excepción el flujo del programa se dirige al final de ese bloque, buscando un bloque catch que capture la excepción (si no lo encontrara, el programa terminaría -ver sección 6.4-). En este caso, la instrucción catch(…) captura cualquier excepción, y en particular, la excepción bad_alloc. El tratamiento que se efectúa es, en este caso, mostrar un mensaje de error y terminar la ejecución del programa. Ejemplo. El siguiente programa (proyecto Division) lee dos valores y calcula el cociente entre ambos. Si el divisor es cero, se intenta realizar una división por cero y el programa lanza una excepción de división por cero (E Zero Divide?). //----------------------------------------------------------------

  1. include <vcl.h>
  2. pragma hdrstop

//----------------------------------------------------------------

WINAPI Win Main?(HINSTANCE, HINSTANCE, LPSTR, int) {

   Ansi String? Valor;
   float Dividendo, Divisor, Cociente;

   // Leer datos de entrada: dividendo y divisor

   Valor = Input Box? (“División”, “Dividendo”, “”); // Leer dividendo y
   Dividendo = Str to Float? (Valor);                 // convertirlo.
   Valor = Input Box (“División”, “Divisor”, “”);   // Leer divisor y
   Divisor = Str to Float (Valor);                   // convertirlo.

   // Calcular cociente. Zona critica: peligro si Divisor == 0

   Cociente = Dividendo / Divisor;

   // Mostrar el resultado

   Show Message? (“Cociente = “ + Ansi String(Cociente));

   return (0);

} //---------------------------------------------------------------- Cuando se produce la excepción, al no estar tratada por el programa, el entorno se hace cargo de ella y muestra la siguiente ventana: Figura 6.1. Ventana de error que surge debido a una excepción E Div by Zero? no tratada.

Para proteger la instrucción crítica, recoger y tratar la excepción, introducir la siguiente modificación:

   try {
      Cociente = Dividendo / Divisor;
      Show Message (“Cociente = “ + Ansi String(Cociente));
   }
   catch (…) {
      Show Message (“El divisor no puede ser cero.”);
   }

Para ceder el control de la gestión de excepciones a nuestro programa debemos desabilitar la opción por la que el entorno integrado gestiona las interrupciones e indicar que se van a gestionar por el programa: seleccionaremos Tools | Debuggber Options y abriremos la carpeta OS Exceptions para dejarla como se indica en la figura 6.2. Figura 6.2. Ventana Debugger Options

Con esto indicamos al depurador de C++ Builder que nuestro programa se encargará de manejar las excepciones C++ que ocurran. Ahora, al ejecutar el programa e intoducir el valor 0 como divisor se muestra la ventana mostrada en la figura 6.3 Figura 6.3. Ventana resultante de la gestión de la excepción.


Google