Cómo entender y prevenir las fugas de memoria en Delphi

El soporte de Delphi para la programación orientada a objetos es rico y poderoso. Las clases y los objetos permiten la programación modular de códigos. Junto con los componentes más modulares y complejos, vienen los errores más sofisticados y complejos.

Mientras que desarrollar aplicaciones en Delphi es (casi) siempre divertido, hay situaciones en las que sientes que todo el mundo está en tu contra.

Siempre que necesites usar (crear) un objeto en Delphi, necesitas liberar la memoria que consumió (una vez que ya no era necesario).

Seguramente, los bloques de prueba/de protección de la memoria pueden ayudarle a prevenir fugas de memoria; todavía depende de usted salvaguardar su código.

Una fuga de memoria (o recurso) ocurre cuando el programa pierde la capacidad de liberar la memoria que consume. Las fugas de memoria repetidas hacen que el uso de la memoria de un proceso crezca sin límites. Las fugas de memoria son un problema grave: si tiene un código que causa fuga de memoria, en una aplicación que se ejecuta las 24 horas del día, los 7 días de la semana, la aplicación consumirá toda la memoria disponible y, finalmente, hará que la máquina deje de responder.

Fugas de memoria en Delphi

El primer paso para evitar las fugas de memoria es comprender cómo ocurren. Lo que sigue es una discusión sobre algunas trampas comunes y mejores prácticas para escribir código Delphi sin fugas.

En la mayoría de las aplicaciones (simples) de Delphi, donde se utilizan los componentes (Botones, Memos, Editar, etc.) que se dejan caer en un formulario (en tiempo de diseño), no es necesario que se preocupe demasiado por la gestión de la memoria.

Una vez que el componente se coloca en un formulario, el formulario se convierte en su propietario y liberará la memoria tomada por el componente una vez que el formulario se cierra (se destruye). Form, como propietario, es responsable de la deslocalización de memoria de los componentes que alojaba. En resumen: los componentes de un formulario se crean y se destruyen automáticamente.

Un simple ejemplo de fuga de memoria: En cualquier aplicación Delphi no trivial, usted querrá instanciar componentes Delphi en tiempo de ejecución. También tendrás algunas de tus propias clases personalizadas. Supongamos que tiene una clase TDeveloper que tiene un método DoProgram. Ahora, cuando necesite utilizar la clase TDeveloper, cree una instancia de la clase llamando al método Create (constructor). El método Create asigna memoria para un nuevo objeto y devuelve una referencia al objeto.

var

   zarko : TDeveloper

begin

   zarko := TMyObject.Create;

   zarko.DoProgram;

end;

¡Y aquí hay una simple fuga de memoria!

Siempre que cree un objeto, debe disponer de la memoria que ocupaba. Para liberar la memoria de un objeto asignado, debe llamar al método Free. Para estar perfectamente seguro, también debe utilizar el bloque de prueba / finalmente:

var

   zarko : TDeveloper

begin

   zarko := TMyObject.Create;

   try

    zarko.DoProgram;

   finally

     zarko.Free;

   end;

end;

Este es un ejemplo de una asignación de memoria segura y un código de deslocalización.

Unas palabras de advertencia: Si desea instanciar dinámicamente un componente de Delphi y liberarlo explícitamente algún tiempo después, siempre pase nil como propietario. El no hacerlo puede introducir riesgos innecesarios, así como problemas de rendimiento y mantenimiento del código.

Un simple ejemplo de fuga de recursos: Además de crear y destruir objetos utilizando los métodos Create y Free, también debe tener mucho cuidado al utilizar recursos "externos" (archivos, bases de datos, etc.).

Digamos que necesitas operar con un archivo de texto. En un escenario muy simple, donde el método AssignFile se usa para asociar un archivo en un disco con una variable de archivo cuando terminas con el archivo, debes llamar a CloseFile para liberar el gestor de archivos que empieza a usarse. Aquí es donde no tienes una llamada explícita a "Libre".

var

   F: TextFile;

   S: string;

begin

   AssignFile(F, 'c:\somefile.txt') ;

   try

     Readln(F, S) ;

   finally

     CloseFile(F) ;

   end;

end;

Otro ejemplo incluye la carga de DLLs externas desde su código. Siempre que utilice LoadLibrary, debe llamar a FreeLibrary:

var

   dllHandle : THandle;

begin

   dllHandle := Loadlibrary('MyLibrary.DLL') ;

   //do something with this DLL

   if dllHandle <> 0 then FreeLibrary(dllHandle) ;

end;

¿Fugas de memoria en.NET?

Aunque con Delphi para.NET el recolector de basura (GC) gestiona la mayoría de las tareas de memoria, es posible que haya fugas de memoria en las aplicaciones.NET. He aquí un artículo sobre GC en Delphi para .NET.

Cómo luchar contra las fugas de memoria

Además de escribir código modular de seguridad de memoria, la prevención de fugas de memoria se puede hacer utilizando algunas de las herramientas de terceros disponibles. Las herramientas de reparación de fugas de memoria de Delphi le ayudan a detectar errores de aplicación de Delphi, como corrupción de memoria, fugas de memoria, errores de asignación de memoria, errores de inicialización de variables, conflictos de definición de variables, errores de punteros y mucho más.

(0 votes)