2012-03-27 4 views
8

Supongamos que al inicio se crea una aplicación con algunos formularios y solo un módulo de datos. En el evento DM1.OnCreate, se crea un TStringList para ser utilizado en tiempo de ejecución. Sabemos que cuando se finaliza la aplicación, todas las cosas se destruirán y la memoria se liberará automáticamente. Liberar algo puede llevar algo de tiempo, por lo que no siempre se recomienda preocuparse por las pérdidas de memoria al apagar. Ver por ejemplo this answer de Barry Kelly o this post de Raymond Chen.¿Existe, además de buscar fugas de memoria, otra situación en la que debería liberar todos los objetos al destruir una aplicación?

Además de eso, FastMM informa de la pérdida de memoria si no agrego TStringList.Free a DM1.OnDestroy. Esto resulta ser un problema cuando busco cualquier otra fuga de memoria que deba preocuparme por realmente.

Básicamente, estoy preguntando si/por qué/cuándo debería liberar instancias de objeto que serán liberadas por la aplicación o el sistema operativo (Windows en este caso específico). ¿Hay algún otro caso válido que no sea cuando se buscan fugas de memoria?

NOTA: En este caso específico, el módulo de datos no se crea ni se vuelve a crear más veces. No habrá ninguna pérdida de memoria, además de la. La fuente de desechos del módulo de datos:

unit UDM1; 

interface 

uses SysUtils, Classes, ...; 

type 
    TDM1 = class(TDataModule) 
    procedure DataModuleCreate(Sender: TObject); 
    procedure DataModuleDestroy(Sender: TObject); 
    procedure DoStuffWithStringList1(Sender: TObject); 
    private 
    internalStL: TStringList; 
    end; 

var 
    DM1: TDM1; 

implementation 

procedure TDMInterfacePAFECF.DataModuleCreate(Sender: TObject); 
begin 
    internalStL := TStringList.Create(); 
end; 

procedure TDMInterfacePAFECF.DataModuleDestroy(Sender: TObject); 
begin 
    internalStL.Free; //<-- IS THIS NECESSARY OR ADVISED? 
end; 

procedure DoStuffWithStringList(Sender: TObject); 
begin 
    //Place some code using internalStL here... 

end; 
+3

has olvidado "end." al final (: es broma, siempre libero la memoria que estoy asignando, pero así soy yo, es cierto que Windows se lo liberará al salir de la aplicación, pero también es cierto que en muchos casos nunca se sabrá por Asegúrese de cómo se comportará su aplicación en el futuro, por lo que si está creando instancias en Create del módulo datamodule, sería prudente (en mi humilde opinión) liberarlas en Destroy, ese es mi $ 0.02 (: – ComputerSaysNo

Respuesta

7

Por la misma razón, yo abogo firmemente (subestimación) por no dejar ningún Indice o advertencia del compilador en un proyecto, limpie después de usted mismo y ¡NO DEJE UNA FUGA DE MEMORIA NOTIFICADA!
NUNCA!

Ahora, no es que lo hace necesariamente significa que usted tiene para Liberar todo en el destructor de su módulo de datos si usted tiene un caso fuerte para no hacerlo, pero en ese caso, es necesario registrar su pérdida de memoria por lo que no será informado. (Y ponga allí un comentario muy visible para justificar y explicar por qué)

Pero considere el hecho de que puede dejar este proyecto y dentro de un año, alguien más lo está manteniendo y tiene un nuevo requisito comercial para crear múltiples DataModules. Las posibilidades son que si no conocen lo suficiente el interior de su código, confiarán en que su código estará limpio y es probable que surjan problemas.

Así que les recomiendo vivamente contra de no liberar a no ser que en un caso muy especial y esperado y documentado ...

PS: Visto que y tuvo que limpiar el goteo de memoria todo el lugar tantas veces que me incluso hicieron algunas sesiones CodeRage en la lucha contra las pérdidas de memoria ...

Updayte: Aquí está el enlace para descargar that CodeRage session ...

+1

+1 no podría estar más de acuerdo! – jpfollenius

+0

Estoy aceptando esto. De todos modos, para referencia futura, debe tener en cuenta que la respuesta @NGLN muestra la forma de registrar la pérdida de memoria esperada. – EMBarbosa

+1

@EMBarbosa, para referencia futura, agregué el enlace a una sesión de CodeRage; un poco viejo pero lleno de información relevante (registrando la pérdida de memoria esperada incluida). :-) –

4

Déjame responder haciéndote una pregunta.

¿Se puede decir con certeza que el ciclo de vida del módulo de datos será siempre estar ligada a la vida útil de la aplicación o que se Nunca necesitará crear instancias adicionales de la misma?

Si responde afirmativamente, no dude en ignorar las prácticas de gestión de memoria estándar.

Si responde no, entonces debe asegurarse de que los objetos se limpien después de ellos.

+1

Sí. Vea la nota en la pregunta. Entonces, ¿crees que, además de buscar fugas de memoria, no hay ninguna otra motivación para liberarlo? – EMBarbosa

+6

Para evitar reforzar un mal hábito, quizás. Lo diré de otra manera. En el momento en que alguien cambia el código para que su suposición sobre la vida útil del objeto ya no sea cierta. Se ha introducido una pérdida de memoria ** real ** –

+0

Además de este caso de ejemplo, no ocurrirá, ahora hizo un buen punto. +1 – EMBarbosa

7

Mi respuesta puede considerarse filosófica, pero la razón principal es que cualquier acción (o ausencia de ella) tiene consecuencias. Pensé en tu ejemplo y probablemente en otros ejemplos y veo una buena razón para liberar el objeto. Cada vez que creo que puedo ignorar el objeto libre, aumenta la probabilidad de no hacer esto en otra situación, quizás más grave. Otro ejemplo es el hábito de hacer "probar finalmente el fin" dondequiera que se asigna o libera algo. No me importa liberarme en caso de excepción, pero este hábito me ayuda a evitar fugas

+1

+1 En el ejemplo anterior: ¿y si en algún punto de f Si decide reutilizar su DM, cree varias instancias de la misma. Cada creación de DM crea TStringList. Cada destrucción de DM no destruye TStringList = Por lo menos has desperdiciado memoria. Lo cual podría empeorar si haces que tu DM forme parte del servicio de Windows que corre mucho tiempo. Personalmente, hago todo lo que puedo para liberar cada objeto que creo solo para evitar posibles problemas cuando el código se reutiliza. –

5

Use RegisterExpectedMemoryLeak para las fugas de memoria intencionales. La rutina tiene algunas versiones sobrecargadas de los cuales uno se puede FEAD con una clase de objeto:

begin 
    RegisterExpectedMemoryLeak(TStringList); 
    FStringList := TStringList.Create; 
    ... 

o mejor, registrar el propio puntero:

begin 
    FStringList := TStringList.Create; 
    RegisterExpectedMemoryLeak(FStringList); 
    ... 

En este caso las pérdidas de memoria inesperados se mostrarán normalmente y no se puede confundir con esta lista de cuerdas en particular.

+1

¿Pero por qué es esto mejor que simplemente liberar el objeto? Es más largo escribir, más difícil de entender, potencialmente más lento, una excepción innecesaria a las reglas usuales de administración de memoria ... – jpfollenius

+1

@Smasher Sí, pero es lo que OP quiere. Como él dice: _La liberación de algo puede llevar algo de tiempo_. Tal vez la lista de cadenas no sea un buen ejemplo a ese respecto, pero un hilo [seguramente podría ser] (http://stackoverflow.com/q/9029730/757830). – NGLN

+0

@Smasher De hecho, si ve los dos enlaces que he publicado, encontrará que no se espera perder tiempo en liberar algo que se liberará y no en absoluto en contra de las reglas de administración de memoria. – EMBarbosa

2

materia se hace cuando se libera un objeto, posiblemente más entonces sólo desasignar la memoria.

Me viene a la mente un objeto de base de datos que realiza transacciones y finaliza todas las transacciones iniciadas en el ondestroy.

Si no llama gratis, ondestroy no se disparará y puede terminar con tablas bloqueadas.

Cuestiones relacionadas