[RESUELTO] Error al salir del programa
#1
Escrito 10 enero 2011 - 01:09
Aqui les dejo la imagen y mientras me gustaria saber como manejar esta excepcion para que no me de error cuando cierro el programa. Luego les pondre una imagen de la linea del componente zeos donde se sale el programa.
#2
Escrito 10 enero 2011 - 03:37
function TZIBEventAlerter.GetPlainDriver: IZInterbasePlainDriver; begin Result := (FConnection.DbcConnection as IZInterbase6Connection).GetPlainDriver; end; { TIBEventThread }
Esta es la linea que se resalta cuando salgo del programa y estoy en delphi. Alguien menos ciego que yo, podria decirme que significa esto.
#3
Escrito 10 enero 2011 - 03:49
Tu ya sabes que no uso Zeos, pero intentaré darte algo de ayuda.
¿Por casualidad no liberas algún componente? ¿Podrías poner el código que tienes en el OnClose y/o OnCloseQuery?
Habría que realizar una traza para ver que línea de tu código provoca esa excepción... Lo más lógico, por el error que comentas y la línea de código, es pensar que haces uso de un TZIBEventAlerter el cual fue liberado.
Sin ver tu código está difícil la cosa.
Saludos,
#4
Escrito 10 enero 2011 - 07:47
Tengo un boton que es que utilizo para cerrar la aplicacion y tiene el siguiente codigo:
procedure TFRMactivasred.salidaClick(Sender: TObject); var f: TForm; begin f := Dialogs.CreateMessageDialog('REALMENTE DESEA SALIR', dialogs.mtConfirmation, dialogs.mbOKCancel); f.Color := clBlue; f.Font.Color := clLime; if f.ShowModal = mrOk then BEGIN Timermonitoreo.Enabled:=false; DMmonitorenred.ZConmonred.Disconnect; Application.Terminate; END; end;
Esto es lo mismo que tiene el onclosequery.
#5
Escrito 10 enero 2011 - 07:59
.........Esto es lo mismo que tiene el onclosequery.
¿Y porque repites el código?, si lo tienes en el evento OnCloseQuery, solo deberías necesitar eso:
procedure TFRMactivasred.salidaClick(Sender: TObject); var f: TForm; begin f := Dialogs.CreateMessageDialog('REALMENTE DESEA SALIR', dialogs.mtConfirmation, dialogs.mbOKCancel); f.Color := clBlue; f.Font.Color := clLime; if f.ShowModal = mrOk then close; end;
Salud OS
#6
Escrito 10 enero 2011 - 08:04
Esto es lo mismo que tiene el onclosequery.
Umm, si por "esto es lo mismo" te refieres a que ese código está repetido en el OnCloseQuery entonces el error es evidente, o al menos infiero por donde va los tiros.
Fíjate en la línea:
DMmonitorenred.ZConmonred.Disconnect;
Si es como yo lo entiendo, y esa misma instrucción está en el OnCloseQuery, entonces ese Zconmonred en su método Disconnect libera algo de la memoria. De ser cierto, ante la pulsación del botón y la confirmación del diálogo entonces se libera el objeto.
Luego, al dispararse el evento OnCloseQuery se vuelve a ejecutar las mismas instrucciones... por tanto al volver a confirmar, se intentará volver a liberar un objeto que fue liberado. Conclusión: un AccessViolation.
La solución pasaría por hacer que el botón dispare el OnCloseQuery y no repetir el código.
Ahora bien si yo he entendido mal, te pediría que te explicases mejor y nos brindaras más información.
Saludos,
#7
Escrito 10 enero 2011 - 08:07
#8
Escrito 10 enero 2011 - 08:09
#9
Escrito 10 enero 2011 - 08:11
Gracias Egostar, eso pensaba yo, pero entonces despues que le doy ok, me repite el mismo cuadro y tengo que vover a darle ok para cerrar el programa.
Pues, mas fácil, quita todo el código del botón y sólo deja el Close; en el evento OnCloseQuery se hará todo.
Salud OS
#10
Escrito 10 enero 2011 - 08:16
if f.ShowModal = mrOk then Application.Terminate else CanClose := false;
Salud OS
#11
Escrito 10 enero 2011 - 08:22
Delphius la verdad es que no he liberado el evento TZIBEventAlerter en ningun lado, pero leyendo lo que me indicaste he comentado la linea:
DMmonitorenred.ZConmonred.Disconnect;
y con esto el error desaparecio. Mi duda ahora es si es que al no haber liberado el eventalerter al intentar disconectarme me salta el error.
Que problemas puede tener el no hacer la desconexion.
por ahora no hay error y ademas tengo menos codigo. gracias a los dos
#12
Escrito 10 enero 2011 - 08:28
Sólo para complementar, en el evento OnCloseQuery necesitas validar si deseas que se termine o no la aplicación, de otra forma no hará caso de la pregunta "REALMENTE DESEA SALIR"
delphi
if f.ShowModal = mrOk then Application.Terminate else CanClose := false;
Salud OS
talvez ese era el problema de porque no funcionaba el boton solo, porque en el onclosequery lo tengo como indicas, pero en el boton no estaba completo. gracias de nuevo.
#13
Escrito 10 enero 2011 - 09:07
El asunto es que ese método Disconnect libera algo. Tu no liberas en forma explícita, pero dentro de ese componente Zeos, algo se libera cuando se ejecuta el método. De ese modo, cuando primero se ejecuta el código de botón se libera y luego, cuando se ejecutaba el evento OnCloseQuery y se confirmaba se volvía a intentar a liberar el mismo... y como ya había sido liberado es que se recibe el Access Violation.
La solución, como te habíamos comentado pasaba por hacer que el botón invocase a Close y dejar el código a evento OnCloseQuery que hiciera el trabajo.
Saludos,
#14
Escrito 10 enero 2011 - 09:31
procedure TFRMactivasred.FormCloseQuery(Sender: TObject; var CanClose: Boolean); var f: TForm; begin f := Dialogs.CreateMessageDialog('REALMENTE DESEA SALIR', dialogs.mtInformation, dialogs.mbOKCancel); f.Color := clBlue; f.Font.Color := clLime; if f.ShowModal = mrOk then BEGIN Timermonitoreo.Enabled:=false; // DMmonitorenred.ZConmonred.Disconnect; Application.Terminate; END else canclose := false; end;
#15
Escrito 10 enero 2011 - 10:03
Recuerden bien que el Terminate internamente libera todo los objetos (en realidad el objeto de la variable global Application). Luego Application derivaba las órdenes en sus forms.
Aquí ya depende del valor de la variable Action del OnClose. Si el valor de dicha variable es caFree se obliga al compilador a liberar toda la memoria (formularios y controles creados).
Quizá en parte el problema esté allí.
Ten en cuenta, además, de que los DataModules se crean ANTES que los forms (al menos de forma predeterminada), y el hacer un Terminate se fuerza a finalizar el sistema contra su voluntad y no seguir los cursos normales (sobre todo si los DataModules se crean de forma dinámica). En teoría al finalizar el formulario principal de forma abrupta corta el hilo principal de ejecución, con lo cual quedarían los DataModules sin liberar y por consiguiente sus controles.
La buena práctica indica que deben "cerrarse" y liberarse los DataModules PRIMERO y luego ya el form principal.
Habría que investigar mejor tu sistema luk2009 para saber donde está el problema... Haz una traza paso a paso y vuelve sobre tus pasos. Revisa tu código por si estás liberando algo... El principal motivo de un AccessViolation es un intento de acceder a una memoria liberada pero no es el único...
Hay que estudiarlo, sin tener más información... estaremos adivinando.
Saludos,
#16
Escrito 10 enero 2011 - 10:35
gracias por tu tiempo delphius.
#17
Escrito 10 enero 2011 - 11:01
voy a revisar lo que me dices y voy a liberar el datamodule primero y luego el form principal a ver que pasa. Si aun asi no funciona entonces voy a revisar paso a paso y te muestro la linea del error.
gracias por tu tiempo delphius.
O bien puedes ir al menu de Delphi --> Search --> Goto Address y en la ventana que te muestra poner la dirección $00590999, la cual te llevará a la línea donde está el error. Casi estoy seguro que en las versiones de Delphi hasta la 7 se llama Find Error, en las versiones 2006 en adelante Goto Address.
Tienes que pausar la ejecución del programa, puedes poner un Breakpoint y cuando se pause hacer lo que ya te mencioné.
Salud OS
#18
Escrito 11 enero 2011 - 05:36
function TZIBEventAlerter.GetPlainDriver: IZInterbasePlainDriver; begin Result := (FConnection.DbcConnection as IZInterbase6Connection).GetPlainDriver; end; { TIBEventThread }
Egostar la linea del result es la que se resalta con el find error.
#19
Escrito 11 enero 2011 - 07:30
¿Puedes rastrear la línea de TU código que lleva hacia ese error? Sigue los pasos que te comenta Egostar añadiendo breakpoints y ve línea a línea o algunos grupos de líneas ayudándote con las teclas F7, Shift+F7 y F8.
Acompañate de las ventanas de debug, y examina el resultado o contenido de algunas de las variables objeto.
Se que es un proceso tedioso y lento pero no hay otro modo, debes hacerlo desde tus unidades, viendo tu código para ver como se va propagando hasta llegar a las unidades Zeos.
El punto es que es NECESARIO encontrar la línea de tu código que lleva al error, y no la línea de la unidad Zeos que lo provoca.
Es evidente que el problema está en un componente Zeos, es fundamental hallar al culpable... puede ser el TZIBEventAlerter, o el FConnection o quizá el DbcConnection que está asociado...
Pero viendo esa línea de código es difícil... hay que rastrear justo la última línea de tu código que lleva a ese error y de allí empezar a rastrear al culpable hasta el lugar en el que es liberado. Porque de algún modo algún objeto es liberado...
Estamos ciegos luk2009, bastante ciegos. Sin tener una ojeada de tu código lo máximo que podemos hacer es tirar unos cuantos palos al aire para ver si de casualidad le pegamos a un transeúnte y le preguntamos ¿Che... vos sos el que está causando problemas?
Por ello te digo que vayas con las ventanas de debug, más que nada con la ventana Watches, y también la Evaluate/Modify.
Hay que salir de la biblioteca Zeos... hay que ver el problema desde tu código. No te vayas tan adelante.
Si el error está indicando en el método de TZIBEventAlerter es una buena elección empezar a rastrear todo lo que se hace con el componente; desde que se crea y donde se lo va utilizando, si es éste el que se libera en algún momento se debería llegar a un .Free.
Saludos,
#20
Escrito 11 enero 2011 - 07:39
if Assigned(ElObjetoX) then showMessage('El objeto X está vivo') else showMessage('El objeto X está muerto. Cuidado... utilizarlo provoca un AV');
Siendo ElObjetoX el nombre de tus componentes/objetos que utilices. Empieza con tus objetos TZIBEventAlerter y luego con otros objetos.
Si el error viene cuando se cierra la aplicación es conveniente que esa prueba se haga en OnClose o en OnCloseQuery.
Esta prueba sencilla podría ayudar a rastrear al desgraciado. Si es que realmente el AccessViolation es causado por un intento de utilizar un objeto ya liberado. Al menos el mensaje de error indica que el AV se presenta cuando se intenta leer una zona de memoria 0, eso indica que un componente o control está liberado.
Saludos,