FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
||||
|
||||
Raised Exception
Buenas Tardes, se me produce el siguiente error:
"Project SIGECO.exe raised exception class EAccessViolation with message 'Violación de acceso en la dirección 00503A36 en módulo 'SIGECO.EXE'. Leer de dirección 'FFFFFFFF'. Process stopped. Use Step or Run to continue" Le he realizado una traza y no indica el punto exacto del código donde se produce el error, pero ocurre en todos los formularios que cierro a través de código. Dichos formularios se han creado utilizando el siguiente código: Código:
Application.CreateForm(TFormClass(listaclass[i]),Pantalla[j]); IndicePantalla := j; Pantalla[j].Show; Código:
Pantalla[i].Close; Pantalla[i].Free; Pantalla[i] := nil; Se produce el error, se acepta el mensaje y todo continua,pero claro los usuarios se preocupan y da una imagen muy pobre de la aplicación Será muy bienvenida cualquier sugerencia. Gracias a todos. Un saludo. |
#2
|
||||
|
||||
¿Lo has ejecutado paso a paso y verificado si i tiene el valor que tu crees que tiene?
__________________
delphi.com.ar Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla. |
#3
|
|||
|
|||
tambien pasa cuando remueves las formas del proyecto..
si es que las removiste debes de usar el showmodal y no nada mas show.. saludos desde Puebla Mexico asanxt@hotmail.com |
#4
|
|||
|
|||
Cita:
El error FFFFFFFF aparece cuando intentamos acceder a una clase que no se ha creado (falta la línea "myclass.create(parametros)") Espero que se entienda |
#5
|
||||
|
||||
Muchas gracias por vuestras contestaciones, voy a verificar que el item del array al que intento acceder no es nulo y que el indice del mismo es exactamente al que se supone debo acceder.
Cuando tenga los resultados os los hare llegar. Gracias de nuevo. |
#6
|
||||
|
||||
Hola a todos, ya he verificado que el indice del array es el correcto y que el valor de ese item no es NULL y es accesible.
Realizando la traza, no se detiene en ninguna línea de codigo, sino que tras terminar el código que debe ejecutar, saca el error, sin realizar parada en línea alguna. Si se os osurre alguna cosa más que verificar será muy bién venida. Gracias, un saludo. |
#7
|
|||
|
|||
Vuelvo a mirar el código que pones y me he dado cuenta de que:
el close, Free, nil, lo deberias poner en la ventana que utilizas con el Show, no en la que lo llama, más o menos así: procedure Tform1.FormClose(Sender: TObject; var Action: TCloseAction); begin action:=cafree; end; si fuera Showmodal si que podrias realizarlo con el código que escribes. |
#8
|
||||
|
||||
Es cierto, debería haber puesto el código cmpleto, ya que en realidad, hace lo siguiente:
Código:
Pantalla[i].Close; if (Pantalla[i] <> NULL) then begin Pantalla[i].Free; Pantalla[i] := nil; end; Gracias por contestar. |
#9
|
|||
|
|||
Si utilizas un showmodal, el código de la función se detine en ese punto, en cambio si utilizas show no, por lo que el código sigue y se libera el form, con lo que o no lo puedes utilizar o no tiene tiempo a ejecutar el código y da errorres como los que te da
ejempo código con showmodal Tform1.funcion1 begin Form2:=Tform2.Create(self); Form2.Showmodal; Form2.free; end; ejempo código con showmodal Tform1.funcion1 begin Form2:=Tform2.Create(self); Form2.Show; //no hay free end; Tform2.Close ..... begin action:=caFree; end; |
#10
|
|||
|
|||
perdona las prisa, corrigo el anterior
Si utilizas un showmodal, el código de la función se detine en ese punto, en cambio si utilizas show no, por lo que el código sigue y se libera el form, con lo que o no lo puedes utilizar o no tiene tiempo a ejecutar el código y da errorres como los que te da Código:
ejempo código con showmodal Tform1.funcion1 begin Form2:=Tform2.Create(self); Form2.Showmodal; Form2.free; end; Código:
ejempo código con show Tform1.funcion1 begin Form2:=Tform2.Create(self); Form2.Show; //no hay free se debe liberar en el propio formulario end; Tform2.Close ..... begin action:=caFree; end; |
#11
|
||||
|
||||
Gracias Julia.T por responder. Te comento un poco más el funcionamiento que tiene la aplicación:
Desde la pantalla principal, que nunca se cierra salvo para finalizar la aplicación, es donde se construyen los formularios, cuando se selecciona la opción de menu, que a su vez construyo dinamicamente basándome en la base de datos donde están las autorizaciones que tenga cada usuario, así como las opciones de menú asociadas y el nombre de cada uno de los formularios que se deben lanzar. Se utiliza Show y no Showmodal, por que no es el formulario padre quien libera al formulario, sino que en módulo aparte es donde tengo el procedimiento de liberación. Además si utilizase ShowModal, quedaría restringida la utilización de opciones de menú diferentes al mismo tiempo (sabemos que eso no es posible, pero sí podemos ir cambiando de formulario en la ejecución) Es decir el main crea la clase y lanza el formulario, asignando a un array global de clases el formulario creado. El formulario creado puede terminar su ejecución de dos maneras: 1.- Haciendo click en la cruz superio derecha, con lo que se llama al evento close del formulario: Código:
Procedimiento Close del formulario Pantalla[i].Free; Pantalla[i] := nil; Código:
Procedimiento Global de Liberación Pantalla[i].Close; if (Pantalla[i] <> NULL) then//No se ejecuta Nunca begin Pantalla[i].Free; Pantalla[i] := nil; end; Muchas Gracias de nuevo Julia, espero haberme explicado un poco mejor esta vez. Un saludo |
#12
|
|||
|
|||
¡Entendido!
Me pasó lo mismo en un programa que hize en Delphi 2, ya hace mucho, lo solucioné colocando un manipulador de exepciones global y acallando el error (creo que luego colocando el Action:=caFree en el onclose dejó de hacerlo, y creo que es por eso que siempre coloco este código en los close). Si estamos en Delphi 5 o superior existe un componente llamado ApplicationEvents en la paleta addictional que tiene un evento llamado onException. Tan solo nos hará falta colocar algo de código Código:
procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception); begin // end; el ApplicationEvents lo deberás colocar el la ventana que se produce el error, sea la principal u otra. Si tienes delphi 4 o inferior, deberia recuperar el programa, para acordarme de como lo hacia. Espero que esto si te sirva finalmente |
#13
|
|||
|
|||
Ocultar la excepcion no es una solucion, es un gravisimo error , porque el bug en el programa sigue existiendo, es como si para parar una epidemia los medicos decidiesen ocultar los cadáveres para que "no se note" .
Si se produce una excepcion de ese tipo, es posible que alguna parte del programa (variables por ejemplo) se machaquen al azar, o que otros objetos no hayan podido ser destruidos porque una excepcion hace que la ejecucion del programa se interrumpa bruscamente en algun punto. De modo que a partir de una excepcion de ese tipo cualquier programa quedara en un estado "inestable" no se puede garantizar que siga funcionando correctamente o (lo que es peor) que los resultados que de sean correctos, hasta que se cierre y se vuelva a ejecutar. Salud2 !!! |
#14
|
|||
|
|||
por cierto al puslar la tecla esc se finaliza todo el código tipo
tecla=esc => begin Close; exit; end; o bien queda algo colcago por finalizar tecla=esc => begin Close; end; .... continua el código |
#15
|
||||
|
||||
Hola Juliá, este es el código del KeyDown donde se trata la tecla ESC:
Código:
//Pulsacion de Cancelar (ESC) if (Key=VK_ESCAPE) then begin if not(DataSource3.DataSet.State in [dsInsert,dsEdit]) then begin Key := 0; LiberaPantalla(numpantalla); end else DBEdit18.SetFocus; Exit; end; Tiene el Exit al final, porque dentro del KeyDown trato muchas mas teclas y como no puedo utilizar un Case, me veo obligado a hacerlo con if...else. Por eso pongo el Exit, para que no continue con los if...else. ¿Comentas lo del código al final, porque intentaría ejecutar el Exit sobre algo que ya no existe?. Gracias. Un saludo. |
#16
|
|||
|
|||
intenta colocar el exit dentro de la condición aunque creo que no soluciones nada
if (Key=VK_ESCAPE) then begin if not(DataSource3.DataSet.State in [dsInsert,dsEdit]) then begin Key := 0; LiberaPantalla(numpantalla); exit; end luego te envio el código que utilizo yo para crear y cerrar una ventana no modal desde otra |
#17
|
|||
|
|||
Te muestro el código que utilizo para mostrar los informes de manera no modal y cerrarlos desde una ventana que no es la propia.
El inconveninete que tiene es que de esta manera no se puede acceder a ningun valor ni funcion de la ventana (solo mostrar y cerrar) Código:
type TInformes = class(TForm) ... public class procedure Mostrar(ATag: integer); class procedure Tancar; end; Var VTag:integer; class procedure TInformes.Mostrar(ATag:integer); Var I:integer; F:Tform; begin For I:=Screen.FormCount-1 downto 0 do begin F:=Screen.Forms[i]; if (F is Self) and(Atag<>0) then begin if (F.Tag=Atag) or (F.Tag+1000=Atag) then begin f.show; F.BringToFront; exit; end; end; end; VTag:=ATag; F:=Create(Application); F.FormStyle:=fsMDIChild; F.WindowState:=wsMaximized; F.BringToFront; end; class procedure TInformes.Tancar; Var I:integer; F:Tform; begin For I:=Screen.FormCount-1 downto 0 do begin F:=Screen.Forms[i]; if (F is Self) then F.Close; //and tag=num end; end; |
#18
|
||||
|
||||
Hola Julià, muchas gracias por tu última respuesta y por el código. Resulta que es bastante similar a como lo hago yo. Te lo adjunto:
1.- Código de creación de Forms Código:
procedure TMainForm.AbrirForm(); var i, j : integer; a : boolean; begin i := 0; j := 1; a := true; while (a) do begin if (Screen.Forms[i].Name = PDatItem(TreeView1.Selected.data) ^.Pantalla) then a := false else begin if (i < (Screen.FormCount - 1)) then i := i+1 else begin a := false; i := 1000; end end end; if (i < 1000) then Screen.Forms[i].Show else begin i := 0; While (i < listaclass.Count) and (listaclass[i].ClassName <> PDatItem(TreeView1.Selected.data)^.TPantalla) do inc(i); if (i < listaclass.Count) then //hemos encontrado la clase begin While (Pantalla[j] <> nil) and (j <= 25) do inc(j); Application.CreateForm(TFormClass(listaclass[i]),Pantalla[j]); IndicePantalla := j; Pantalla[j].Show; end end end; Gracias Julià, si le vieses algo al código, por favor coméntamelo. Un saludo. E |
#19
|
|||
|
|||
Hola:
He rehecho el código para ir deprisa he hecho mi propia adaptación, me funciona correctamente. Código:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Controls, Forms, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Edit1: TEdit; Button3: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private Index:integer; listaclass:array[1..10] of TFormclass; listpant:array[1..10] of TForm; function Existe(Nombre: string): boolean; public { Public declarations } end; var Form1: TForm1; implementation uses Unit2, Unit3; {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin //relleno los arrays con los forms y TForm //creo que en tu caso son diferentes listaclass[1]:=TForm2; listaclass[2]:=TForm3; listpant[1]:=Form2; listpant[2]:=Form3; end; function TForm1.Existe(Nombre:string):boolean; Var i:integer; begin //busca en las ventanas creadas si existe la muestra Result:=False; For I:=Screen.FormCount-1 downto 0 do if Screen.Forms[i].Name = Nombre then begin Result:=True; Screen.Forms[i].Show; break; end; end; procedure TForm1.Button1Click(Sender: TObject); var i: integer; Nombre:string; begin //muestra o crea la ventana con el nomre indicado en el edit1.text Nombre:=Edit1.text; if Existe(Nombre) then exit; For i:=Low(listaclass) to High(listaclass) do begin if Assigned(listaclass[i]) and (listaclass[i].ClassName='T'+Nombre) then begin Application.CreateForm(listaclass[i],listpant[i]); // listpant[i]:=listaclass[i].Create(Self); //no hay problema también sirve Index := i; listpant[Index].Show; end; end; end; procedure TForm1.Button2Click(Sender: TObject); begin //esto cierra la última que has abierto sólo la última if Assigned(listpant[Index]) then FreeAndNil(listPant[Index]); //if Assigned(listpant[Index]) then listpant[Index].Close; //no hay problema también sirve //prefiero el close end; procedure TForm1.Button3Click(Sender: TObject); var i: integer; Nombre:string; begin //Cierra la ventana indicada en el Edit1.text Nombre:=Edit1.text; For I:=Screen.FormCount-1 downto 0 do if Screen.Forms[i].Name = Nombre then Screen.Forms[i].Close; end; end. |
#20
|
||||
|
||||
Muchas Gracias Julià. Voy a intentar adaptar el código que me has pasado a mi aplicación. En cuanto tenga los resultados te los comento.
Gracias de nuevo. Un abrazo. |
|
|
|