FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
|
#1
|
|||
|
|||
Bueno, conozco el FreeAndNil, pero no lo suelo usar...manias...
Lo q quiero decir con crear, viendo lo comentado y según me acuerdo, (es un programa q hice hace 1 año) es q yo creaba un cliente y un servidor. TServerSocket TClientSocket El procedimiento para cada uno era tener una clase por cada y dentro de ella declarar un servidor o un cliente y q esa clase le controle su comportamiento... Entonces, a estos les pasaba al crearlos el TComponent del formulario. Entonces al destruir la clase q contenía el TServerSocket no me dejaba hacer un FreeAndNil del objeto, en cambio, con el TClientSocket si me dejaba... Creo recordar q me comí un poco la cabeza probando formas diferentes para q no cascase, pero al final opté por q lo libere la aplicación al destruirse, ya q dependía del formulario principal... Este caso, me mosqueo, xq me parecía q hacia todo bien
pero no me dejaba luego liberarlo, al hacerlo me salía un error. Pos eso, muchas gracias... |
#2
|
||||
|
||||
Explicación detallada:
Tu hacias un .Free del SSocket, se libera pero no queda apuntando a nil el valor de SSocket, por tanto, cuando el Aowner se destruye, accede a SSocket, ve que es distinto de nil, e intenta liberar una zona de memoria que ya ha sido liberada => Access Violation. Si hubieras usado Freeandnil(SSocket), cuando el Aowner va a destruirlo con .Free, se detecta que SSocket es = nil, y por tanto, no se destruye, No hay Access Violation. Moraleja: Haz un curso de autoControl y quitate la manía que tienes con FreeAndNil Un saludo |
#3
|
|||
|
|||
Que yo sepa, FreeAndNil es lo mismo q poner un objeto Free y luego igualarlo a nil. Ya se q son 2 pasos en vez de uno pero creo q són lo mismo.
Me parece extraño q no lo haya probado, más bien diría imposible, (no poner FreeAndNil, sino, ponerlos por separados, Free y luego nil...) en el ejemplo del TServerSocket. Si evito poner FreeAndNil es xq en mis inicios me dio algunos problemas q resolví quitandolo...seguramente sería por ser novato y si algo me da problemas he aprendido a evitarlos y buscar otra forma de hacerlo. Hoy pienso q sería por otra cosa pero aún asi, intento evitarlo porsiaca. He cargado una prueba q tenía de cuanto investigé los TServerSocket, y le he puesto FreeAndNil y casca, al igual q poner Free y luego Nil...en la prueba lo he puesto en el FormDestroy, luego lo he probado con un botón para crear un ServerSocket y otro para eliminarlo y me ha funcionado...asi q debe ser por ponerlo en el FormDestroy. ¿Xq´ casca en el Destroy? Ya q si tengo el método para eliminarlo en el Destroy pero anteriormente con el botón q creé para eliminar el Server lo pulso, entonces no casca (ya q en el destroy miro si está asignado), sólo casca si está creado el ServerSocket y lo libero en el Destroy... |
#4
|
||||
|
||||
como ves se hace al revés ¿Por qué? Porque puede ocurrir alguna excepción al tiempo de liberar el objeto, y entonces no quedaría apuntando a nil, y el peligro sería el mismo. En cuanto a lo demás, sería mejor que pegaras el código que te da error; ya que tengo mis dudas en eso de usar FormDestroy, ¿no querrás decir FormClose? De hecho nunca se debe llamar a destroy, siempre se debe usar .Free sencillamente por esto:
Si primero se usa FreeAndnil, la siguiente llamada a .Free no causará daño alguno. Si se usa FreeAndNil y despues .Destroy, seguro que casca porque Destroy no comprueba el valor de nil. Un saludo Un saludo |
#5
|
|||
|
|||
Hola a todos, yo creo que tengo el mismo error... y me estoy volviendo LOOOOCO y no logro resolverlo. Seguramente sea una tontería, pero es que NO LO LOGRO.
Explico mi caso. Estoy haciendo el modelo de negocios de un hotel, el cual explico brevemente: - Clase THabitaciones (hereda de TComponent), que es básicamente una lista con componentes THabitacion (o TBaseHabitacion). - Clase THabitacion (hereda de TComponent), representa una habitación como tal. Está formada basicamente por dos partes, Un componente GUI: TBaseGUI y un objeto Info: TBaseInfo. - Clase TBaseGUI (hereda de TComponent), es el tope de una jerarquia para la representación gráfica de las habitaciones. - Clase TBaseInfo (hereda de TObject), es el tope de una jerarquia para la información de las habitaciones. Va variando según el tipo en tiempo de ejecución. En el form principal hago lo siguiente en el evento OnClose: Código:
... TiposHabitaciones.Free; Habitaciones.Free; La idea es: 1.- Destruir Habitaciones: THabitaciones (cuando creo una Habitacion: THabitacion hereda de TComponent y el Owner es Habitaciones, con lo cual automáticamente se liberan todas las THabitacion cuyo Owner sea Habitaciones). 2.- Cuando se destruye una Habitacion: THabitacion, básicamente tengo que destruir la Info pues hereda de TBaseInfo que a su vez hereda de TObject. GUI no hay que destruirlo, pues se autodestruye porque tiene como Owner la Habitacion 3.- Cuando se destruye un GUI: TGUIHab, debo liberar el bitmap. A continuación pondré los métodos de destrucción de las clases en ese orden: 1.- Destrucción de Habitaciones: (en realidad no hago nada salvo Lista.Clear y Lista.Free). Código:
Debug('THabitaciones.Destroy: ComponentCount:' + IntToStr(ComponentCount)); Debug('THabitaciones.Destroy: FLista.Count:' + IntToStr(FLista.Count)); for i := 0 to FLista.Count -1 do begin H := ItemsByPos[i]; if Assigned(H) then begin if H.Owner <> nil then Debug(H.Caption + ' Owned by: ' + TComponent(H.Owner).Name); // H.FreeInfo; // H.FreeGUI; // H.Free; end; // Lista.Objects[i].Free; end; Lista.Clear; Debug('THabitaciones.Destroy: ComponentCount:' + IntToStr(ComponentCount)); Lista.Free; Debug('La lista interna ha sido liberada'); inherited Destroy; 2.- Destrucción de Habitacion: Tengo qeu destruir sólo la Info (pero está comentado, pues sospecho que me da error en el Assigned(Info)) pues el GUI tiene como Owner la Habitación y se destruirá solo. Código:
Debug(Caption + ': THabitacion.Destroy: ComponentCount:' + IntToStr(ComponentCount)); if Assigned(Info) then begin Debug(Caption + ': TBaseHab.Destroy - assignado. Tipo:' + Info.ClassName); // FreeInfo; // FreeGUI; end else Debug(Caption + ': TBaseHab.Destroy - no assignado'); Debug(Caption + ': THabitacion.Destroy: ComponentCount:' + IntToStr(ComponentCount)); inherited Destroy 3.- Destrucción de GUI. Código:
if Assigned(Owner) then begin Debug('Liberando bitmap de GUI de la habitacion: ' + TComponent(Owner).Name); FreeResources; end; Debug('TGUIHabIcon: ComponentCount=' + IntToStr(ComponentCount)); //TODO: LLamar al heredado? La destrucción de Info no hace nada salvo llamar al heredado. Al cerrar la aplicación obtengo un precioso mensaje : "Invalid pointer operation." (EInvalidPointer) Alguien me puede echar una mano con esto, por favor. Le estaré muy agradecido, pues no logro detectar el error... Creo que falla en el if Assigned(Info) de THabitacion.Destroy, pero no estoy seguro y además no sé cómo resolverlo. Muchas gracias de antemano y disculpen por el mensaje tan largo. PD: A continuación adjunto la pila, por si pueda ser útil. ------------------------------------------------------------------------------------------------ |Address |Module |Unit |Class |Procedure/Method |Line| ------------------------------------------------------------------------------------------------ |40003364|rtl90.bpl |System.pas | |Error | | |400031AB|rtl90.bpl |System.pas | |_FreeMem | | |40003198|rtl90.bpl |System.pas | |_FreeMem | | |40005DBE|rtl90.bpl |System.pas | |_ClassDestroy | | |40005DBC|rtl90.bpl |System.pas | |_ClassDestroy | | |01658F68|CoreClassHab.bpl|UCGUIHab.pas |TGUIIcon |Destroy |127 | |4003D718|rtl90.bpl |Classes.pas |TComponent |DestroyComponents | | |4003D518|rtl90.bpl |Classes.pas | |TComponent | | |01654CD6|CoreClassHab.bpl|UCHabitaciones.pas|TBaseHabitacion|Destroy |195 | |77D2F3DE|user32.dll | | |SendMessageA | | |77D2F39A|user32.dll | | |SendMessageA | | |0067455A|vcl90.bpl |Comctrls.pas |TCustomListView|Scroll | | |40006B58|rtl90.bpl |System.pas | |_LStrArrayClr | | |003F203E|CoreLog.bpl |ULog.pas | |Log |64 | |4003D718|rtl90.bpl |Classes.pas |TComponent |DestroyComponents | | |4003D518|rtl90.bpl |Classes.pas | |TComponent | | |01655442|CoreClassHab.bpl|UCHabitaciones.pas|THabitaciones |Destroy |429 | |400059D4|rtl90.bpl |System.pas |TObject |Free | | |400059CC|rtl90.bpl |System.pas |TObject |Free | | |01654433|CoreClassHab.bpl|UClassObjects.pas | |CoreClassHabDestroy |30 | |01654424|CoreClassHab.bpl|UClassObjects.pas | |CoreClassHabDestroy |29 | |01715794|CoreMain.bpl |UPrincipal.pas |TFrmPrincipal |FormClose |357 | |
#6
|
|||
|
|||
gracias por las aclaraciones
Gracias por tus aclaraciones, Lepe. Pero es un tema difícil de seguir, ya que realmente el compilador explota, y cuesta mucho encontrar el punto donde sucede esta explosión. He tenido este problema en el componente que discutimos en el hilo Override eventos On... (http://www.clubdelphi.com/foros/showthread.php?t=25540)
Si en el destroy del objeto repaso si debo destruir el objeto creado con he concluido lo que describo en el comentario //... Lo que quiere decir que si el Tform creado esta generado como no Modal, se ha liberado automáticamente por si mismo, por lo menos su puntero ¿no?, pero si es Modal si pasa por el código y realiza el FreeAndNil(Explorador). Depurando es muy difícil de seguir esto, ya que se reciben los típicos avisos de Access Violation Address con matrículas que a los mortales no nos dicen nada, y cuesta encontrar en que línea de código sucede, ya que el compilador no la muestra por defecto. Para mi, creo que este es el gran defecto de Delphi, por lo menos su talón de Aquiles.Y entiendo la opción de descartar estas llamadas, por impotencia. Actualmente tengo estos errores al cerrar un proyecto, no se cierra adecuadamente y tengo Access Violation Address ...in module rtl60.dpl se cuelga Delphi simplemente por abrir y cerrar el proyecto, pero no por depurarlo ¿...? incluso el exe rueda OK y no produce errores. Por supuesto cuando sale la ventana de las direcciones de memoria del compilador, para mi es peor que el chino, árabe y japonés todo junto. Si tenéis alguna pista, ...gracias a todos. |
#7
|
||||
|
||||
adlfv: FLista ¿de qué tipo es? Tiene toda la pinta de Tobjectlist o similar, y se puede destruir de otra forma más simple.
Obviamente los errores vienen aqui: |01654424|CoreClassHab.bpl|UClassObjects.pas | |CoreClassHabDestroy |29 y 30 |01655442|CoreClassHab.bpl|UCHabitaciones.pas|THabitaciones |Destroy |429 | |01654CD6|CoreClassHab.bpl|UCHabitaciones.pas|TBaseHabitacion|Destroy |195 | |01658F68|CoreClassHab.bpl|UCGUIHab.pas |TGUIIcon |Destroy |127 | En cuanto a la filosofia, lo veo muy complejo, "este ahora si lo tengo que liberar", "este otro no"... unifica criterios y objetos, los que tengan que liberarse a mano en un sitio y los demás a otro sitio. Y siempre usa Freeandnil, ya que unos hacen referencias a otros. lento manu: Para el tema del número de linea revisa este hilo reciente Saludos |
#8
|
||||
|
||||
¡¡ME VA A DAR UN INFARTO CEREBRAL !!
Ya he perdido la cuenta de cuantos temas se llevan en este hilo al mismo tiempo. ¡¡¡ Por mi salud !!!, abrid un hilo distinto para cada nueva pregunta que vaya saliendo |
#9
|
|||
|
|||
Me he quedado de piedra...
Si q tienes razón q tiene q ser en el close...el caso es q lo he puesto en el FormClose y parece q ya no casca...menudo despiste . Aún asi investigaré en la aplicación q me daba el problema... xq esto era un ejemplo y en una aplicación, me corto las venas si veo q pongo algo en el Destroy..., si encuentro algo raro lo comentaré en este hilo. Por lo otro lado, también admito mi error en lo de FreeAndNil, a partir de ahora le tendré más respeto a dicho método. Bueno, hoy por lo menos he aprendido cosas... Otra preguntita q me ha salido hoy sobre liberar... Estoy con un componente de música q me he bajado, el ACS Audio Components Suite para ulilizar oggs, la cosa es q quiero cerrar el sonido y liberarlo y me da un error... esto lo hago con 2 botones, uno para crear el objeto y otro para liberarlo. En la ayuda encontré q antes de liberar el objeto había q parar la música si estaba sonando, cosa q hice y sigue fallando. Supongo q no conoceis el componente, pero igual teneis esperiencia con música, yo por lo q veo, no le doy tiempo a q se cierre y por eso falla, ya q si pongo en un botón, parar la música y en otro liberarlo y no los pulso muy rápido, pos no salen problemas... He pensado en poner un sleep, pero no me gusta, aunq igual es la única solución q me queda...aunq igual hay algún método q te diga si el objeto está lista para ser liberado... Pos nada, gracias por las contestaciones y por las molestias... |
|
|
|