delphi - etimologia - diferencia entre gratis y gratuito
¿Qué es preferible: gratis o gratis y nil? (5)
@Bharat, la diferencia entre Free
y FreeAndNil
es que, además de la memoria gratuita utilizada por un objeto, FreeAndNil
establece la referencia del objeto en nil.
Puede consultar estos enlaces para discusiones sobre cómo usar Free o FreeAndNil
¿Cuál es la diferencia básica entre Free y FreeAndNil?
¿FreeAndNil = Gratis + Nada?
¿Cuándo debería usar Free y cuándo debería usar FreeAndNil?
No estoy recibiendo estos cuando alguien puede ayudarme.
Gracias por adelantado.
Básicamente, FreeAndNil establece la referencia a cero y luego libera el objeto. Esto lo marca como no asignado. Entonces, la única razón por la que necesitaría usar FreeAndNil es si su código va a reutilizar la referencia. Si estás en un destructor o un bloqueo final, liberando objetos que nunca volverás a tocar, simplemente usa Free.
Ver Delphi Memory Management Made Simple para ver un ejemplo de cuándo lo encontré útil. El comentario de Mghie en la parte inferior también vale la pena leerlo.
Incluso si no parece ser muy diferente a Free, te ayudará mucho más tarde mientras busca el código.
Simplemente piense qué sucede si NO usa FreeAndNil y luego en algún lugar de su código accede a un objeto liberado. Si tiene una mala suerte, su programa se bloqueará cuando se ejecute en casa (sí, eso es un accidente ''bueno''). Si tiene un poco de mala suerte, se bloqueará en la computadora del cliente. ¡Entonces comienza el verdadero dolor!
Como otros ya señalaron, el FreeAndNil en sí mismo no está mal. La función FreeAndNil no está rota / obsoleta o algo así y no dañará su código. Algunos argumentarán que confiar en FreeAndNil puede conducir o indicar un defecto de diseño.
Yo uso FreeAndNil EVEN en una variable local. Su uso en una variable local parece SIN PUNTO, ya que la variable desaparece tan pronto como sale del procedimiento. Sin embargo, es una buena práctica que solo le costará unos pocos bytes adicionales. Piense que puede agregar más código al final del procedimiento, DESPUÉS del punto donde liberó el objeto, código que (obviamente accidentalmente) intentará acceder al objeto liberado. Si el objeto era NIL, BABUM, AV instantáneo ( example ).
Nota: Algunas personas pueden decir que nunca accedieron a un objeto gratis (lo que significa que nunca cometerán errores) por lo que no necesitan FreeAndNil en este caso. Bueno, no soy un robot. Yo hago errores.
Algunas personas conservadoras pueden decir que esta simple llamada desperdiciará recursos de RAM y CPU. Nunca diré que la conservación de la memoria / CPU es mala. ¡Me gusta entregar aplicaciones pequeñas / rápidas / monolíticas también! Pero no creo que eliminar usando FreeAndNil desperdicie más de unos pocos bytes y ciclos de CPU (literalmente pocos). No marcará una diferencia real en la vida cotidiana, especialmente cuando crees que un solo recurso gráfico como un glifo TButton o el ícono de tu programa puede tomar de 50 a 300 KB, y tu programa puede tener docenas de estos.
Pros
Mason Wheeler ya apunta a un artículo que muestra el método de ''creación diferida'' que usa FreeAndNil que todos usamos un día: http://tech.turbu-rpg.com/106/delphi-memory-management-made-simple
Contras
Allen Bauer muestra aquí un ejemplo sobre cómo usar FreeAndNil en el caso A CIERTO (destructor de un componente visual) y ser realmente malo: http://blogs.embarcadero.com/abauer/2010/02/16/38916
Allen afirma que FreeAndNil debe reemplazarse con mejores métodos. Por ejemplo, con FastMM. Sin embargo, aquí hay un código simple en el que FastMM falla, mientras que FreeAndNil lo salva: example
Como hay argumentos pro y en contra de FreeAndNil, depende de usted decidir si le gusta o no.
Ver
- delphibasics-FreeAndNil
- docwiki.embarcadero-FreeAndNil
- pages-freeandnil
- eurekalog-freeandnil
- blogs.embarcadero
- ...
Y eche un vistazo a la implementación:
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
Ejemplos
Considera el siguiente código:
procedure TForm1.FormCreate(Sender: TObject);
var
bm: TBitmap;
begin
bm := TBitmap.Create;
bm.LoadFromFile(''C:/Users/Andreas Rejbrand/Documents/RAD Studio/6.0/Demos/DelphiWin32/VCLWin32/Football/up.bmp'');
bm.Free;
if Assigned(bm) then
bm.SaveToFile(''C:/Users/Andreas Rejbrand/Desktop/test.bmp'')
else
ShowMessage(''Cannot save! The bitmap does no longer exist!'');
end;
Esto creará un error o un mapa de bits inválido (vacío) en mi escritorio, porque trato de usar un objeto que ha sido liberado. Sí, aunque bm
se ha liberado, todavía está "asignado", es decir, bm
aún apunta a una dirección de memoria, aunque no hay nada (utilizable) allí. Para superar esto, uno puede establecer bm := nil
, como salvaguarda, Then assigned(bm)
devolverá false, como uno quisiera. Más o menos, FreeAndNil(bm)
es una abreviatura de bm.Free; bm := nil
bm.Free; bm := nil
. La primera declaración libera toda la memoria (y los recursos del sistema operativo, el tiempo de CPU, etc. utilizados por el objeto) y bm := nil
establece el "puntero" bm
en nil
, de modo que bm
ya no apunta al lugar donde solía estar el objeto , pero ya no lo es. De esta manera usted (y rutinas como assigned
) no se dejarán engañar al creer que todavía hay un objeto de mapa de bits.
Discusión
Algunos dicen que siempre debes usar FreeAndNil(foo)
lugar de foo.Free
. ¿Bueno, por qué no? La instrucción adicional foo := nil
probablemente no tomará demasiados nanosegundos para ejecutarse, y de hecho, se le assigned(foo) = false
una propiedad muy agradable de un objeto liberado. Pero, de nuevo, si sabes lo que estás haciendo, y sabes que nunca volverás a utilizar el objeto foo
después de liberarlo, entonces podrías mantenerte solo foo.free
. Realmente, algunos argumentarían que en muchos casos (pero no en todos), tratar de usar una variable de un objeto liberado es un error en sí mismo. (Por supuesto, hay casos en que lo hace intencionalmente; tiene un objeto foo
que a veces se asigna y otras veces no).
Voy a responder de una manera diferente.
Tal vez, llenar su referencia de objeto con nil
después de liberar su objeto no siempre es una buena idea.
De esta forma, no tiene una distinción entre una referencia que nunca se usó (y, por lo tanto, es nil
) y una referencia que se ha utilizado, pero que no se debe usar en el futuro.
Por lo tanto, llenarlo con un número mágico (similar a lo que el FastMM memoria FastMM puede hacer con el contenido de bloques de memoria cuando esos bloques se liberan).
--jeroen