PDA

Ver la Versión Completa : Error grave al mostrar form


nfrfabian
15-09-2007, 17:52:28
Hola a todos. Tengo un problema muy grabe (por lo menos para mi). Les comento. Tengo una aplicación del tipo MDI, la misma tambien tiene form normales, los que muestro con showmodal. Todos los form del proyecto los crea delphi, yo simplemente me limito a mostrar los form normales cuando los necesito.
La aplicacion se conecta a una base de datos MS SQL, todo funciona bien. Pero tuve 2 veces el mismo problema:
Al mostrar un form normal desde un form MDIChild con la instrucion:

edicion.showmodal,

la aplicación me mostro un mensaje del tipo access violation.
La primera vez el error se produjo cuando ejecutaba la aplicacion sin el entorno de delphi, es decir sola. Como se daran cuenta me aparecio el mesaje de error, se cerro la aplicacion y todo se perdio (trabajo realizado, datos corruptos en la base de datos, etc.)

la segunda vez fue desde delphi, en este caso delphi me muestra el error de access violation, se abre el debugger con toda las instrucciones en ensamblador, trato de seguir corriendo la aplicacion con F8, pero es imposible, me muestra el error y se queda en una instruccion en ensamblador

Normalmente este error no se produce, por esta razon me es imposible detectar cual puede ser el problema.
El form se crea desde el inicio, por esta razon siempre esta disponible. Nunca creo un form por codigo. Los form normales los muestro con la instruccion showmodal y los cierro con la instruccion close.
Este form tiene componentes comunes (edits, labels, dbgrid), cuando tiene que utilizar datos de otro form, lo hace por medio de variables globales que las declaro en el mainform.

Buscando en el foro vi que la mayoria crea los form cuando los necesita y despoues los libera. Esto no lo hago porque en algun lado lei que el crear los form toma su tiempo (seguro que son milisegundos), pero este form lo utilizo mucho por lo que me parece que es mejor que se cree desde el inicio. Quizas estoy equivodado.
Me gustaria saber las ventajas y desventajas de la forma en que yo muestro estos forms, y si tengo que crearlos en el momento que los necesito, seguro que lo hago, pero quiero esta seguro que esto solucionara mi problema. A continuacion les muestro el codigo:

codigo del proyecto:

Application.Initialize;
Application.Title := 'SISTEMA1';
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TAboutBox, AboutBox);
Application.CreateForm(Tcargareserva, cargareserva);
Application.CreateForm(TDataModule1, DataModule1);
Application.CreateForm(Tedicion, edicion);
...

para mostrar el form utilizo:


vcliente := idcliente; // vcliente variable global

edicion.showmodal;

El form edicion realiza un consulta a la base de datos del cliente y muestra los datos en un dbgrid (tambien tiene otros componentes)

En este momento voy a cambiar la forma de crear de este form. Los pasos que voy a seguir son:
quitar la linea del proyecto que crea el form desde el inicio.

despues llamar al form de la siguiente forma:
if not (edicion is Tedicion) then begin edicion := Tedicion.Create(Self); try edicion.ShowModal; finally edicion.Free; end;Si esta no es la forma correcta, les pido que me digan cual es.Escucho cualquier consejo. Gracias.

paldave
15-09-2007, 17:58:07
La forma correcta sería:
if not assigned(edicion) then
edicion := Tedicion.Create(Self);
edicion.ShowModal;
edicion.Free;

No creo que el error se deba a un problema al crear el form, seguramente sea en alguno de los componentes de ese form, probablemente en los relacionados con la base de datos.

nfrfabian
15-09-2007, 22:13:31
Hola, paldave. Te comento que hice la prueba con otro form de la siguiente forma:

if not (resfact is Tresfact) then
begin
resfact := Tresfact.Create(nil);
try
resfact.ShowModal;
finally
resfact.Free;
end;

De esta forma solo se muestra el form la primera vez. Por eso despues probe de esta forma:

resfact := Tresfact.Create(Application);
try
resfact.ShowModal;
finally
freeandnil(resfact);
end;

De esta forma el form se mostror correctamente cerca de 20 veces hasta que la aplicacion se cerro. No me mostro ningun mensaje de error (seguro que no mostro el error porque la instruccion esta dentro de un try), pero igual se cerro, lo que me lleva a pensar en tu comentario de que no es problema de creacion del form sino de algun componente del mismo.

Hice la prueba como vos decis pero delphi no reconoce el parametro self, probe con nil y application, y solo se ejecuta bien la primera vez en la segunda aparece el mesaje de error access violation, pero no el mismo que cierra la aplicacion porque me muestra el mesaje pero la aplicacion sigue funcionando, sin mostrar la ventana pero funcionando. A continuacion como quedo:

if not assigned(resfact) then
resfact := Tresfact.Create(Selft);
resfact.ShowModal;
resfact.Free;
(no se ejecuta porque delphi no reconoce el parametro Self)

if not assigned(resfact) then
resfact := Tresfact.Create(nil);
resfact.ShowModal;
resfact.Free;
y
if not assigned(resfact) then
resfact := Tresfact.Create(application);
resfact.ShowModal;
resfact.Free;

(solo se ejecuta bien la primera vez. La segunda aparece el mesaje de error access violation, el form no se muestra pero la aplicacion sigue funcionando.

Una consulta: el que yo haya puesto dos instrucciones que no conosco en el evento onclose y ondestroy, podra producir el error?

De esta forma el form se mostro correctamente mas de 20 veces:

resfact := Tresfact.Create(Application);
try
resfact.ShowModal;
finally
freeandnil(resfact);
end;

en el evento onclose puese esta instruccion:
action:= caFree;

en el evento ondestroy puse:
self:= Nil;

Estas dos instruciones las saque de algun post, las puse porque alguien dijo que esto puede solucionar algunos problemas que se pueden producir cuando uno crea los form en forma manual. No creo que afecte para nada el funcionamento pero por las dudas consulto.

Volviendo al comentario de que el problema esta en algun componente del form, les consulto esto:
El que en el evento onshow del form tenga varias instrucciones, funciones, dos de estas funciones realizan consultas a la base de datos. Podra producir el error?
Tampoco creo que sea esto porque en los demas form no tengo este problema. Pero talvez es esto. Por favor, escucho consejos, sugerencias. Muchas gracias.

Al González
16-09-2007, 09:07:15
¡Hola! :)

Fuera de tema: Cuando leí el título pensé que se trataba de grabar algo, pero veo que quisiste escribir grave (grande, de mucha entidad o importancia). Una revisión a la ortografía no estaría mal antes de enviar los mensajes, con todo respeto.

Un abrazo.

Al.

nfrfabian
17-09-2007, 02:59:29
hola, Al González.Tenes razón. Pido perdon por mis errores de ortografía. Siempre fuí malo para ese tipo de cosas.

paldave
18-09-2007, 14:03:16
¿Podrías poner el código completo de tu form para analizarlo?

nfrfabian
18-09-2007, 18:47:21
hola paldave. Te comento que poner todo el codigo del form me parece mucho porque el solo el form que hace la llamada con showmodal tiene mas de 5000 lineas. Pongo solo parte del codigo del boton que hace la llamada:



Código Delphi [-] (http://www.clubdelphi.com/foros/#)
...
if (preser[ultimopre5].indicli <> 0) then
begin

//resfact.showmodal;
{
if not (resfact is Tresfact) then
begin
resfact := Tresfact.Create(nil);
try
resfact.ShowModal;
finally
resfact.Free;
end;
}
{
with Tresfact.Create(nil) do
try
ShowModal();
finally
Free();
end;
}
resfact := Tresfact.Create(Application);
try
resfact.ShowModal;
finally
freeandnil(resfact);
end;
{
if not assigned(resfact) then
resfact := Tresfact.Create(selft);
resfact.ShowModal;
resfact.Free;
}
end;
...








siendo preser un tipo de datos propio que es una vector. Quizas el error viene por ese lado porque al ser preser una variable global, en el el evento onshow del form resfact busco datos en la variable y si el indice del vector no es correcto se produce el access violation (En realidad esto me paso a veces pero generalmente, la aplicacion me muestra el error y despues sigue funcionando, no como ahora que directamente se cierra.
Lo que hice fue en el evento onshow de resfact poner lo siguiente:



Código Delphi [-] (http://www.clubdelphi.com/foros/#)
if ultimopre5 <= 200 then
begin
idnombre := preser[ultimopre5].idnombre;
...
end;







De esta forma la aplicacion no se cerro repentinamente en algunas pruebas, pero no estoy seguro que lo que hice fue solucionar el problema, o solo es cuestion de tiempo para que se produzca de nuevo.

nfrfabian
18-09-2007, 18:52:34
hola paldave. Te comento que poner todo el codigo del form me parece mucho porque el solo el form que hace la llamada con showmodal tiene mas de 5000 lineas. Pongo solo parte del codigo del boton que hace la llamada:



...
if (preser[ultimopre5].indicli <> 0) then
begin

//resfact.showmodal;
{
if not (resfact is Tresfact) then
begin
resfact := Tresfact.Create(nil);
try
resfact.ShowModal;
finally
resfact.Free;
end;
}
{
with Tresfact.Create(nil) do
try
ShowModal();
finally
Free();
end;
}
resfact := Tresfact.Create(Application);
try
resfact.ShowModal;
finally
freeandnil(resfact);
end;
{
if not assigned(resfact) then
resfact := Tresfact.Create(selft);
resfact.ShowModal;
resfact.Free;
}
end
...








siendo preser un tipo de datos propio que es una vector. Quizas el error viene por ese lado porque al ser preser una variable global, en el el evento onshow del form resfact busco datos en la variable y si el indice del vector no es correcto se produce el access violation (En realidad esto me paso a veces pero generalmente, la aplicacion me muestra el error y despues sigue funcionando, no como ahora que directamente se cierra.
Lo que hice fue en el evento onshow de resfact poner lo siguiente:




...
if ultimopre5 <= 200 then
begin
idnombre := preser[ultimopre5].idnombre;
end;
...








De esta forma la aplicacion no se cerro repentinamente en algunas pruebas, pero no estoy seguro que lo que hice fue solucionar el problema, o solo es cuestion de tiempo para que se produzca de nuevo.
http://www.clubdelphi.com/foros/images/misc/progress.gif