domingo, 21 de noviembre de 2010

Tratamiento de errores y excepciones

El tratamiento de errores es una técnica recién incorporada al Object Pascal proveniente de C++, por lo que la voy a comentar de su novedad y la seguridad que aporta. En ANALOGIA.EXE se ha intentado preservar la seguridad en la ejecución, por lo que todas las operaciones de alojamiento dinámico de memoria, gestión de ficheros, etc. se realizan como medida de seguridad entre bloques TRY..EXCEPT o TRY..FINALLY, que veremos a continuación.

Los errores se pueden dividir en dos grupos: errores en tiempo de compilación (corregibles antes de hacer funcionar el programa), y errores en tiempo de ejecución, más complicados de encontrar, puesto que el error casi siempre es culpa del usuario y suele manifestarse con frecuencia.
Una excepción es una señal provocada por un error, tal como pueda ser una división por cero, el sobrepasar los límites de un array, o el intento de acceso a los datos apuntados por un puntero nulo.
Por ejemplo:
La excepción generalmente dispone de la información necesaria para conocer la causa del error. Dicha información la podemos aprovechar en nuestro código si interceptamos la excepción, o bien será mostrada en un mensaje antes de que el programa se interrumpa, si no la interceptamos (no es recomendable).
Para interceptar los errores, trataremos de aislar el bloque a proteger entre la palabra Try y la palabra Except, de forma que si vemos en ANALOGIA.EXE el siguiente código:
 
try
  num:=StrToFloat(Value);
for cont:=0 to PanelL.ComponentCount-1 do
  if PanelL.Components[cont] is TCompMecanico then
    begin
    .....................
    .....................
    end
Except   {Excepción si es un valor numérico inválido}
  PanelL.Pan1.Strg1.Cells[1,ARow]:='';
end;
 
se ejecutará lo que hay después de la asignación num:=StrToFloat(Value) solo si se ha producido esta asignación correctamente y no ha habido problemas en el procedimiento StrToFloat. En caso de tener en Value un valor incorrecto, se generará una excepción (que no se muestra al usuario), y se salta directamente al código que hay después de la palabra clave Except. Este código se ha utilizado por ejemplo para evitar que el usuario de valores incorrectos (letras, etc) a los valores de los componentes.
Si observamos este otro trozo de código correspondiente a la escritura de un fichero .MEC en disco:
 
Try Rewrite(Fich);
  for cont:=0 to FormDibu.PanelL.ComponentCount-1 do
    if FormDibu.PanelL.Components[cont] is TCompMecanico then
      begin
      Aux:=FormDibu.PanelL.Components[cont] as TCompMecanico;
      Reg.left:=Aux.left;
      ..................
      ..................
      write (Fich,Reg);   {Escribe componente en el fichero}
      end;
Finally
  CloseFile(Fich);      {Cierra en cualquier caso el fichero}
end;
 
Ahora ocurre lo siguiente: Si la apertura/creación (Rewrite(Fich)) del fichero es correcta, se ejecutará el bucle for cont... y después se ejecutará lo que hay después de Finally (se cerrará el fichero). Sin embargo, si el Rewrite(Fich) provoca un error por cualquier causa (disco lleno, etc.), se saltará directamente al código que hay detrás de Finally, puesto que nos interesará siempre no dejar ficheros abiertos.
Como vemos, con Finally se ejecuta siempre el código que hay a continuación, mientras que con Except se ejecuta solo si se ha producido una excepción. En cualquier caso lo que hay detrás de Try... solo se ejecuta si no se ha producido ningún error.
También es útil un ejemplo de gestión de los errores de memoria que nos muestra también como anidar estructuras Try..Except y Try..Finally:
 
Try
  Try
    New (PNumero);          {Asignar memoria dinámica}
    PNumero:=Dividendo div Divisor;
  Finally
    Dispose (PNumero);      {Liberar siempre recursos}
  end;
Except          {Ejecutar si se produjo una excepción}
  Writeln ('Se produjo una excepción');
end;
 
Estas son las principales herramientas de gestión de excepciones, pero no las únicas (gestión de excepciones según su tipo, creación de excepciones propias, etc.), sin embargo una discusión más amplia del tema se escapa de los límites del proyecto.

1 comentario: