Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Try/except/finally (https://www.clubdelphi.com/foros/showthread.php?t=75680)

jsc 12-09-2011 16:32:38

Try/except/finally
 
Hola,
quisiera saber si podeis ayudarme a controlar posibles fallos en mi aplicación.
en tiempo diseño, constantemente me aparecen excepciones que supongo hacen que la aplicación deje cositas abiertas por ahí, y de vez en cuando, me sale un mensaje:
Código:

falta de memoria
y me obliga a guardar todos los cambios, cerrar todo delphi y volver a abrir todo para seguir trabajando

utilizo codigo del tipo
Código:

TRY EXCEPT
y cuando ejecuto el programa sin estar en modo diseño (sin tener abierto delphi), los comandos que esten puestos en EXCEPT llegan a mostrarse pero hay casos en los que me gustaria saber la manera o forma correcta que deberia programar para mostrar los mensajes correctos y que la aplicación no deje los querys... abiertos y no pueda bloquearme la aplicación... y pueda seguir trabajando; me explico mejor con un ejemplo:
Código:

TRY query1.open;
edit1.text :=query1.fieldbyname ('campo').asstring ;
EXCEPT showmessage ('no se pudo cargar los datos');
END

bueno, por ejemplo, este codigo muestro un mensaje al usuario informandole de que no se puede cargar los datos, porque la por ejemplo en el query no exista el campo "campo"
todo correcto, la cuestion es que posterior a esto, salta una excepción indicando lo mismo en ingles y para mi gusto es algo que no queda nada bien y entiendo que es algo que no tengo controlado o no lo estoy haciendo bien.
podria llegar a poner
Código:

on exception do codigo...
pero quisiera algo general para no tener que controlar todas las excepciones que podria dar.
en el EXCEPT me faltaria poner
Código:

raise
como ultimo comando?
espero haberme explicado y que podais ayudarme
utilizo
Código:

TRY
en operaciones criticas como puedan ser abrir un query, ejecutarlo para actualizar..., cargar datos una vez abierto...

newtron 12-09-2011 16:41:23

Hola.

En el ejemplo que citas si puedes cerrar el query antes del mensaje

Código Delphi [-]
try
  Query1.open;
  Edit1.Text:=Query1.FieldByname('CAMPO').AsString;
except
  Query1.close;
  ShowMessage('No se pudo cargar los datos');
end;

Saludos

jsc 12-09-2011 19:00:58

try/except/finally
 
ok,
ahora no puedo probarlo
mañana comento algo al respecto
seria mejor tratar el try con la excepción correcta? con lo que pongo seria suficiente para cualquier operación que se haria con el query o tendría que tratar alguna excepción más?
Código:

TRY
  query1.open;
  edit1.text := query1.fieldbyname ('CAMPO').asstring ;
EXCEPT On EDatabaseError do
  begin
      query1.close ;
      showmessage ('Error al cargar los datos');
  end;

esto mismo anulando
Código:

on EDatabaseError do
tendría el mismo efecto/resultado?
gracias

Ñuño Martínez 12-09-2011 20:26:48

El "ON" es para filtrar el tipo de excepción, cuando se quiere dar una respuesta diferente para ciertos tipos. Así:
Código Delphi [-]
...
  EXCEPT
    ON Error: EDatabaseError DO
      ShowMessage ('Error en la base de datos.  ¡A saber lo que estabas buscando!');
    ON Error: EInOutError DO
      ShowMessage ('¡Error de entrada y salida!  Chungo lo tienes');
    ON Error: Exception DO
      ShowMessage ('La excepción no es de entrada y salida ni de base de datos.  Aun así, no respires tranquilo');
  END;
Además te permite acceder a los métodos de la excepción, tales como el identificador, el mensaje, etc.

También ten en cuenta que cada bloque filtrará la excepción indicada y todas aquellas de clases derivadas que no hayan sido procesadas ya. Por eso "ON Error: Exception " obtendrá todas las excepciones que no se hayan filtrado. Y por eso es importante el orden en el que se pongan, ya que se pueden ocultar si se ponen en el orden incorrecto (por ejemplo, si pones "ON Error: Exception " la primera, entonces nunca ejecutará el resto).

De todas formas, puedes anidar un "FINALLY" dentro del "EXCEPTION":
Código Delphi [-]
TRY 
  query1.open;
  TRY
    edit1.text := query1.fieldbyname ('CAMPO').asstring ;
  FINALLY
  { Esta línea se ejecuta SIEMPRE, haya o no excepción. }
    query1.close ;
  END;
EXCEPT
  On Error: EDatabaseError DO
    ShowMessage ('Error al cargar los datos: '+Error.Message);
  ON Error: Exception DO
    ShowMessage ('Excepción: '+Error.Message);
END;

jsc 12-09-2011 20:54:41

try/except/finally
 
Cita:

Empezado por Ñuño Martínez (Mensaje 411905)
El "ON" es para filtrar el tipo de excepción, cuando se quiere dar una respuesta diferente para ciertos tipos. Así:
Código Delphi [-]
...
  EXCEPT
    ON Error: EDatabaseError DO
      ShowMessage ('Error en la base de datos.  ¡A saber lo que estabas buscando!');
    ON Error: EInOutError DO
      ShowMessage ('¡Error de entrada y salida!  Chungo lo tienes');
    ON Error: Exception DO
      ShowMessage ('La excepción no es de entrada y salida ni de base de datos.  Aun así, no respires tranquilo');
  END;
Además te permite acceder a los métodos de la excepción, tales como el identificador, el mensaje, etc.

También ten en cuenta que cada bloque filtrará la excepción indicada y todas aquellas de clases derivadas que no hayan sido procesadas ya. Por eso "ON Error: Exception " obtendrá todas las excepciones que no se hayan filtrado. Y por eso es importante el orden en el que se pongan, ya que se pueden ocultar si se ponen en el orden incorrecto (por ejemplo, si pones "ON Error: Exception " la primera, entonces nunca ejecutará el resto).

De todas formas, puedes anidar un "FINALLY" dentro del "EXCEPTION":
Código Delphi [-]
TRY 
  query1.open;
  TRY
    edit1.text := query1.fieldbyname ('CAMPO').asstring ;
  FINALLY
  { Esta línea se ejecuta SIEMPRE, haya o no excepción. }
    query1.close ;
  END;
EXCEPT
  On Error: EDatabaseError DO
    ShowMessage ('Error al cargar los datos: '+Error.Message);
  ON Error: Exception DO
    ShowMessage ('Excepción: '+Error.Message);
END;

ok,
muchas gracias me parece muy completo el aporte
un comentario;entiendo que en el segundo try(el anidado) si ocurriera alguna excepción/error al intentar
Código:

edit1.text:= query1.fieldbyname('campo').asstring
saltaria la excepción del primer TRY sin llegar a ejecutar el FINALLY verdad?
muchas gracias

ecfisa 12-09-2011 21:26:47

Cita:

saltaria la excepción del primer TRY sin llegar a ejecutar el FINALLY verdad?
Hola jsc.

La respuesta ya te la dió Ñuño en el código que mencionás con un comentario:
Código Delphi [-]
 { Esta línea se ejecuta SIEMPRE, haya o no excepción. }

Un saludo.

duilioisola 12-09-2011 23:33:07

Mira este hilo también...

Si después de un try..except te salta una excepción más, seguramente es que tu codigo depende de que se ejecute correctamente el codigo en ese bloque:
Código Delphi [-]
begin
  try
     AbriBaseDeDatos;
  except
     ShowMessage('No pude abrir la base de datos'); 
  end;
  ModificarValorTabla;
end;
En este código te saltará primero el mensaje de que "No puede abrir la base de datos" y luego uno del tipo "Database not Open".
Lo correcto sería:

Código Delphi [-]
begin
  BaseAbierta := False;
  try
     AbriBaseDeDatos;
     BaseAbierta := True;
  except
     ShowMessage('No pude abrir la base de datos');
  end;
  if (BaseAbierta) then
    ModificarValorTabla;
end;

jsc 13-09-2011 18:02:36

try/except
 
ok,
la cosa me queda mas clara; gracias por los aportes
lo unico, he hecho pruebas pero todavia sigue saliendome en ocasiones el mensaje de "insuficient memory..." y lo que comentaba, me obliga a cerrar todo delphi y volver a abrir el proyecto para seguir trabajando y programando.
no se si es algo normal, si le pasa a mas gente o es solo a mi porque algo hago mal.
el caso es que si estoy programando y ejecuto el codigo para ver que tal funciona, se me da el caso que da errores que en tiempo diseño no he contemplado y tengo que modificar el codigo.Hasta aqui todo bien pero si hago cambios para corregir el problema, sigo programando y probando el codigo y se vuelven a dar fallos en más ocasiones, llega un punto en que como decia antes tengo que cerrar todo.
De ahi, mi consulta sobre este hilo, no se si era algo que programaba mal... o es algo que es normal;
si pruebo el codigo y da fallo, salta el mensaje de excepción (no el mensaje que yo tengo puesto en el EXCEPT) y he probado una vez ocurrido esto, seguir ejecutando el codigo con F7, y es entonces cuando observo que salta la excepción que tengo puesto con el TRY y pensaba que haciendo esto, de alguna manera pudirea solucionar el problema de "insuficient memory" pero no es el caso me pasa lo mismo.
hay manera de controlarlo?
espero haberme explicado

newtron 13-09-2011 18:09:10

¿Es posible que durante la ejecución del programa vayas creando objetos que no vayas liberando de la memoria?

jsc 13-09-2011 18:25:44

insuficient memory
 
Cita:

Empezado por newtron (Mensaje 412020)
¿Es posible que durante la ejecución del programa vayas creando objetos que no vayas liberando de la memoria?

es un problema que me persigue desde hace tiempo y en esta ocasión he procurado, crear los forms de la aplicación segun los vaya necesitando a ver si asi corregia el problema.cuando cierro los forms, libero el mismo...
Código:

query1.free;
action:=cafree;

los forms ya estan diseñados pero lo que hago es al ejecutar la aplicacion crear el form principal y segun pulse el boton correspondiente crear y mostrar el que necesite.
el mensaje "insuficient memory" me sale cuando abro algun form y me salta la excepcion en mas de una ocasion.el proceso exacto es:
-probar el codigo
-da errores
-hago cambios, y vuelvo a compilar
-pruebo otra vez el codigo
-da errores
-hago cambios y compilo
-da errores
...
-hago cambios y compilo
-intento probar el codigo y salta la excepcion
-cerrar la aplicación guardando o sin guardar los cambios
-salir de delphi
-abrir delphi y el proyecto
-seguir trabajando

en tiempo de ejecucion no llego a crear ningun control

newtron 13-09-2011 18:44:21

A mi me da ese problema muy raramente cuando me salen muuuuuuuchos errores. A ver si va a ser que tu equipo tiene muchas cosas cargadas en memoria y deja poca disponible para el delphi.

duilioisola 13-09-2011 18:47:01

Yo para cazar los "Memory Leaks" utilizo la unidad MemCheck.
La puedes bajar de aquí.

Básicamente debes ponerla dentro de tu proyecto, como primera unidad.
Lo primero que debe hacer tu aplicación es llamar a MemChk.
Código Delphi [-]
program MiPrograma;

uses
  MemCheck in '..\Utilidades\MemCheck.pas',
  Forms,
  SysUtils,
  ...;

{$R *.RES}

begin
  MemChk;

  Application.CreateForm(TDMMain, DMMain);
  Application.CreateForm(TFMMain, FMMain);

  Application.Run;
end.
Para compilar tu versión de desarrollo debes activar algunos checks en las opciones de compilacion:
Mira aquí.
No olvides activar la opción TD32 debug information en la pestaña Linker.

Ejecutas el programa y al salir te da información en un texto que debería serte útil para buscar lugares donde no liberas objetos.

Nota: Luego de agregar MemCheck al proyecto y haber tocado las opciones de compilación, deberías borrar todas las *.dcu para recompilar completamente tu proyecto.
Nota 2: Con las opciones de compilacion puestas el .exe es mucho más grande. Solo deberías utilizar estas opciones durante el desarrollo. Antes de entregar al cliente deberías quitar todas las opciones y comentar la línea //MemChk;

jsc 13-09-2011 18:47:41

Cita:

Empezado por newtron (Mensaje 412024)
A mi me da ese problema muy raramente cuando me salen muuuuuuuchos errores. A ver si va a ser que tu equipo tiene muchas cosas cargadas en memoria y deja poca disponible para el delphi.

pues no se, seria cuestion de hacer pruebas teniendo solo cargado delphi o incluso viendo la memoria disponible cuando arranca...
probare
el caso es que me tiene un tanto preocupado por si es algo que no hago bien, que no controlo, que se me escapa en la programacion y demas.
si ya le pasa a alguien mas puedo darme un respiro
gracias por todo

newtron 13-09-2011 18:58:41

Cita:

Empezado por duilioisola (Mensaje 412025)
Yo para cazar los "Memory Leaks" utilizo la unidad MemCheck.

Tomo nota, gracias. :)

jsc 13-09-2011 19:06:14

mem check
 
creo que me sera de gran ayuda
gracias duilioisola por el aporte


La franja horaria es GMT +2. Ahora son las 11:17:17.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi