sábado, 22 de setiembre de 2007

/identificando memory leaks



Por cuestiones de performance, me vi obligada a chequear los memory leaks de una aplicación desarrollada en Visual C++. Esto es, identificar aquella memoria que fue pedida a demanda (mediante new) y el programa ya no usa, y no se ha liberado (no se realizó el delete correspondiente). O sea algo asi como 'crear' nuestro garbage collector.

Las consecuencias de este consumo indebido de memoria pueden ser varias, desde enlentecer el rendimiento de la aplicación, hasta provocar comportamientos erráticos en otras aplicaciones abiertas o en la propia aplicación.

Buscando info en la web, vi que esto no solo se aplica a C/C++, sino que además puede darse en C# lenguaje con su propio garbage collector.
El administrador de memoria puede recuperar la memoria que quedó fuera del alcance del sistema o fuera de uso, pero no puede liberar aquella memoria que aun permanece al alcance o potencialmente en uso (y no lo está).
El alcance de la memoria se define cuando hay referencias directas o indirectas a ella. Y mientras las haya el administrador de memoria las ignora.
Ejemplo: agregar items a una lista, y olvidar quitarlas (borrarla de memoria) cuando terminamos el procedimiento. El administrador no podrá saber si esa entrada será referenciada nuevamente a menos que algo en el código del programa lo indique.

Este artículo de msdn
explica en mas detalle los memory leaks en memoria no administrada bajo C# (viene con código).

Remitiéndome a mi problema en C++, y particularmente Visual C++, encontré una función que indica en una ventana si tenemos 'memoria colgada' o no liberada.

Para habilitar las funciones de heap al debug, hay que agregar al programa, y en este orden:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>


crtdbg.h, mapea las funciones malloc y free con las versiones de las mismas en el depurador, _malloc_dbg y _free_dbg respectivamente, las cuales registran la memoria pedida y liberada. (Este mapeo sucede al depurar)

#define mapea la versión de las funciones del heap (CRT) correspondientes con las versiones de las mismas en el depurador. (No es necesaria, pero si la omitimos la información obtenida será menos descriptiva)

Agregadas las sentencias previas, en el programa hay que incluir la siguiente sentencia:


Cuando el programa se corre desde el debugger _CrtDumpMemoryLeaks muestra información sobre la memory leak en la ventana de salida.

Me basé en la siguientes referencias
codeguru (con ejemplos), msdn2.microsoft


Para
Delphi, existen las siguientes opciones (no probé ninguna) :
  • memCheck (freeware con código) la versión actual 2.75 es para Delphi 5.1, Delphi 6, Delphi 7, Delphi 2005 y Delphi 2006 (aunque no ha sido probada en las dos últimas). Ofrece una unidad (unit, simil de header para los que usan C/C++/C#) con funciones para el chequeo de memoria.
  • euroekalog, componente que se integra al ide (versión de prueba)


Aplicaciones independientes de cualquier compilador/IDE
Hay entornos de desarrollo o compiladores que no ofrecen esta facilidad, por lo tanto debemos recurrir a aplicaciones que nos dan esa información.
Esta es una lista de aplicaciones razonablemente completa y descriptiva sobre alguna de ellas.

De las mas conocidas (y probadas por mi) está IBM Rational Purify (solo para Windows) que puede descargarse en versión de prueba, (o bueno, está eMule o algun cliente torrent).
Realiza un análisis en tiempo de ejecución sobre los siguientes características de un programa: corrupción de memoria, memory leaks, rendimiento de la aplicación, cheque del registro de windows.

Para Linux existe una aplicación gratuita con similares características a la anterior, Valgrind.







No hay comentarios.: