Anuncios

Bienvenidos sean a este post, hoy veremos que significa administrar la memoria heap.

Anuncios
Anuncios

De lo visto en el post anterior podemos sacar como conclusion que el ciclo de vida de la memoria dinamica o la ubicada en el heap ira desde que la ubicamos en memoria a traves de malloc o calloc hasta ser liberada por medio de free, esta accion en un programa se la llama administracion de memoria, aunque por lo general cuando salimos de un programa al mismo tiempo se libera todo tipo de memoria, ya sea automatica o dinamica, pero se considera una practica descuidada ignorar la administracion de memoria, especialmente para programas muy complejos o de mucho tiempo de ejecucion.

Anuncios
Anuncios

La cantidad de memoria que debemos administar en el heap es dependiente del programa y a su vez es una consideracion que depende de la complejidad y tiempo de ejecucion del programa, por lo tanto si nosotros tenemos informacion en el heap pero que durante el tiempo de ejecucion practicametne no es alterado produce que la administracion del heap no sea necesaria y puede ser aceptable que se la mantenga en memoria hasta que termine el programa sin necesidad de llamar a la funcion free, en cambio si el programa es muy complejo o hace un gran uso de la memoria heap o el tiempo es extremadamente largo, en estos caso la administracion de memoria es fundamental, porque puede ocasionar un cierre anormal del programa, una cuestion a considerar es que para ciertas estructuras de datos la gestion de memoria es relativamente sencilla, pero para otros casos no es tan sencilla o simple y cuando ignoramos la administracion o no la manejamos de forma adecuada nos puede ocasionar un inconveniente comun llamado fugas de memoria (memory leaks).

Anuncios

Este es justamente uno de los principales problemas con la administracion de memoria, esto sucede cuando un bloque de memoria es ubicado y perdemos el apuntador al mismo y no podra ser liberado hasta que el programa finalice, un ejemplo simple puede ser:

Carta* aCarta = (Carta*)calloc(1, sizeof(Carta));
...
aCarta = (Carta*)calloc(1, sizeof(Carta));
Anuncios

Aqui por ejemplo primero crearemos un apuntador a un bloque en la memoria heap pero nuestra fuga ocurre en la segunda linea porque nuestro bloque se vuelve a ubicar pero sin un apuntador asignado por lo tanto no puede ser liberado, para evitar esto primero se deberia haber llamado a free, uno mas sutil puede ser el siguiente caso:

struct Cosa1{
	int tam;
	strut Cosa2* aCosa2;
}

struct Cosa1* aCosa1 = (struct Cosa1*)calloc(1, sizeof(Cosa1));
Cosa1->aCosa2 = (struct Cosa2*)calloc(1, sizeof(Cosa2));
...
free(aCosa1);
Anuncios

Aqui tenemos un ejemplo simple donde primero definimos una estructura llamada Cosa1, con un variable y luego un apuntador a otra estructura llamada Cosa2, primero ubicamos en la memoria heap a un apuntador para Cosa1, luego hacemos lo msmo pero para el apuntador interno a Cosa2 que se encuentra en esta estructura, despues trabajamos con el codigo hasta la ultima linea y ahi viene nuestra fuga de memoria, esto es asi porque al liberar el apuntador aCosa1 tambien destruimos al apuntador a Cosa2 por lo tanto todo aquello que apuntaba a esta estructura no podra ser accedido, lo cual nos puede derivar en un error, la forma correcta de salir es:

free(aCosa1->aCosa2);
free(aCosa1);
Anuncios

De esta forma primero eliminaremos toda referencia de ese apuntador para despues eliminar tranquilmanete el otro apuntador y no dejar ningun cabo suelto, una tercera forma muy sutil puede ser la siguiente:

Carta* CrearCarta( ... )
{
	Carta* aCarta = (Carta*)calloc(1, sizeof(Carta));
	IniciarCarta(aCarta,...);
	return aCarta;
}
Anuncios

Si tomamos el proyecto que estuvimos viendo en posts anteriores, el juego de cartas, vamos a la funcion encargada de crear una carta para luego ser utilizado y al momento de definir un apuntador lo hacemos por medio calloc, lo iniciamos y lo devolvemos, no deberiamos tener ninguna falla, por el momento pero si la utilizamos de la siguiente manera:

Carta* aCarta = CrearCarta(...);
MostrarCarta(aCarta);
aCarta = CrearCarta(...);
MostrarCarta(aCarta);
Anuncios

Al momento de la definicion del apuntador creando la carta y mostrandola no tendremos inconvenientes, el problema lo tenemos cuando lo redefinimos ya que al momento de redefinirlo puede sobreescribirlo en lugar de agregarlo por lo tanto podemos tener un apunte equivocado al momento de utilizarlo, para solucionar esto deberiamos hacerlo de la siguiente manera:

Carta* aCarta = CrearCarta(...);
MostrarCarta(aCarta);
free(aCarta);
aCarta = CrearCarta(...);
MostrarCarta(aCarta);
free(aCarta);
Anuncios

Debermos liberarlo antes de volverlo a asignar, permitiendo que hagamos un mejor seguimiento de las bloques asignados en la memoria heap, vamos a suponer ahora el siguiente caso:

Carta* aJugador = (Carta*)calloc(3, sizeof(Carta*));
for(int i=0; i < cCartasEnMano; i++)
{
	aJugador[i] = CrearCarta(...);
	MostrarCarta(aJugador[i]);
}
...
for(int i=0; i < cCartasEnMano; i++)
{
	free(aJugador[i]);
}
free(aJugador);
Anuncios

Primero definiremos un apuntador a un bloque de 3 cartas, en lugar de apuntar a 3 bloques disitintos para cada carta, despues por medio de un for asignaremos las cartas a posicion de este apuntaddor y mostramos a cada una de ellas, utilizamos nuestro codigo para finalmente liberarlos pero para eviar inconvenientes primero liberamos cada posicion del bloque y una vez liberados todos los elementos internos procedemos a eliiminar el global, como pueden darse cuenta siempre lo hacemos desde adentro hacia afuera para evitar dejar referencias que queden sin un destino, si tienen este cuidado no tendran inconvenientes a la hora de trabajar de esta forma.

Anuncios

En resumen, hoy hemos visto como administrar la memoria heap, como es el ciclo de vida, que se nos produce cuando no hacemos una buena administracion, las denominadas fugas de memoria (memory leaks), y por ultimo algunos ejemplos donde se produce esto, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50