Manejo de memoria dinámica

Sobre el tratamiento de memoria, GLib dispone de una serie de instrucciones que sustituyen a las ya conocidas por todos malloc, free, etc. y, siguiendo con el modo de llamar a las funciones en GLib, las funciones que sustituyen a las ya mencionadas son g_malloc y g_free.

Reserva de memoria.

La función g_malloc posibilita la reserva de una zona de memoria, con un número de bytes que le pasemos como parámetro. Además, también existe una función similar llamada g_malloc0 que, no sólo reserva una zona de memoria, sino que, además, llena esa zona de memoria con ceros, lo cual nos puede beneficiar si se necesita un zona de memoria totalmente limpia.

gpointer g_malloc (gulong numero_de_bytes );

gpointer g_malloc0 (gulong numero_de_bytes );

Existe otro conjunto de funciones que nos permiten reservar memoria de una forma parecida a cómo se hace en los lenguajes orientados a objetos. Esto se realiza mediante las siguientes macros definidas en GLib /gmem.h:

   1         /* Convenience memory allocators
   2         */
   3         #define g_new(struct_type, n_structs)           \
   4                 ((struct_type *) g_malloc (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
   5         #define g_new0(struct_type, n_structs)          \
   6                 ((struct_type *) g_malloc0 (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
   7         #define g_renew(struct_type, mem, n_structs)    \
   8                 ((struct_type *) g_realloc ((mem), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
   9 

Como se puede apreciar, no son más que macros basadas en g_malloc, g_malloc0 y g_realloc. La forma de funcionamiento de g_new y g_new0 es mediante el nombre de un tipo de datos y un número de elementos de ese tipo de datos, de forma que se puede hacer:

   1         GString *str = g_new (GString,1);
   2         GString *arr_str = g_new (GString, 5);

En estas dos líneas de código, se asigna memoria para un elemento de tipo GString, que queda almacenado en la variable str, y para un array de cinco elementos de tipo GString, que queda almacenado en la variable arr_str.

g_new0 funciona de la misma forma que g_new, con la única diferencia de que inicializa a 0 toda la memoria asignada. En cuanto a g_renew, ésta funciona de la misma forma que g_realloc, es decir, reasigna la memoria asignada anteriormente.

Liberación de memoria.

Cuando se hace una reserva de memoria con g_malloc y, en un momento dado, el uso de esa memoria no tiene sentido, es el momento de liberar esa memoria. Y el sustituto de free es g_free que, básicamente, funciona igual que la anteriormente mencionada.

void g_free (gpointer memoria_reservada );

Se presenta un ejemplo sencillo sobre el uso de g_malloc () y de g_free ().

Ejemplo 6-8.1. Uso de g_malloc () y g_free ().

   1 /* ejemplo del uso de g_malloc y g_free */
   2 #include <glib.h>
   3 int main (int argc, char *argv[])
   4 {
   5         gchar *text;
   6         gint len = strlen ("Hola a todos") + 1;
   7         text = g_malloc (len);
   8         g_snprintf (text, len, "Hola a todos");
   9         g_print ("%s\n", text);
  10         g_free (text);
  11         return 0;
  12 }

Realojamiento de memoria.

En determinadas ocasiones, sobre todo cuando se utilizan estructuras de datos dinámicas, es necesario ajustar el tamaño de una zona de memoria (ya sea para hacerla más grande o más pequeña). Para eso, GLib ofrece la función g_realloc, que recibe un puntero a memoria que apunta a una región que es la que será acomodada al nuevo tamaño y devuelve el puntero a la nueva zona de memoria. El anterior puntero es liberado y no se debería utilizar más:

gpointer g_realloc (gpointer memoria_reservada , gulong numero_de_bytes );

Perfil de uso de memoria.

Un perfil de uso de memoria es la información sobre el uso de memoria que hace nuestra aplicación. Para obtener un perfil de nuestro programa se hace uso de la siguiente función:

void g_mem_profile (void );

Para que se obtenga la información sobre el uso de memoria de nuestra aplicación se debe de inicializar una tabla de perfiles de memoria, esto se logra mediante la variable extern GMemVTable *glib_mem_profiler_table; la cual se debe de usar conjuntamente con g_mem_set_vtable() la cual debe ser llamada antes que cualquier otra función de glib.

Veamos un ejemplo sobre su uso:

Ejemplo 6-8.2. Uso de g_mem_profile ()

   1 /* ejemplo del uso de g_mem_profile */
   2 #include <glib.h>
   3 int main (int argc, char *argv[])
   4 {
   5         gchar *text;
   6         gint len = strlen ("Hola a todos") + 1;
   7         g_mem_set_vtable (glib_mem_profiler_table);
   8         text = g_malloc (len);
   9         g_snprintf (text, len, "Hola a todos");
  10         g_print ("%s\n", text);
  11         g_free (text);
  12         g_mem_profile ();
  13         return 0;
  14 }

El resultado es el siguiente:

Figura 6-8.1. Salida de g_mem_profile ().

mem_profile.png

Primero se invoca g_mem_set_vtable (). para la preparación del ambiente y asi obtener un perfil de la memoria empleada, y antes de finalizar pedimos un resumen con la función g_mem_profile ().


Volver a: GLib