Está en la página 1de 13

Administracin de almacenamiento

El manejo de la memoria es uno de los temas que interesan a los programadores, diseadores e implementadores de lenguajes. Tpicamente los lenguajes contienen varias caractersticas o restricciones que podran ser explicadas solamente por las intenciones de los diseadores, para permitir que una u otra tcnica de almacenamiento sea usada. Por ejemplo, en Fortran existe la restriccin de efectuar solamente llamadas no recursivas a subprogramas. Este tipo de llamadas podra ser permitido en Fortran sin efectuar algn cambio en la sintaxis, pero su implementacin requerira un stack en tiempo de corrida de puntos de retorno de las subrutinas, que es una estructura que requiere de almacenamiento dinmico. As, Fortran puede manejar solamente almacenamiento esttico. Otros lenguajes, como Pascal, estn diseados para permitir el manejo de almacenamiento basado en stacks. Tambin hay lenguajes como LISP, que permiten la recoleccin de basura en la memoria. Cada diseo de lenguaje normalmente permite el uso de ciertas tcnicas de manejo de memoria. Los detalles del mecanismo, y su representacin en hardware y software son tareas del implementador. Veamos ahora como la mayora de los programas y sus elementos requieren almacenamiento durante la ejecucin del programa.

Principales elementos que requieren espacio en tiempo de ejecucin


Segmentos de cdigo para los programas de usuario. Una gran parte de los bloques de almacenamiento debe ser reservada para guardar los segmentos de cdigo que representan los programas de usuario. Programas del sistema en tiempo de ejecucin Otra parte sustancial del bloque de almacenamiento durante la ejecucin debe ser reservada para los programas de sistema que soporten la ejecucin de programas del usuario. Estas pueden ser desde simples rutinas de libreras, por ejemplo de funciones matemticas o funciones que impriman cadenas hasta intrpretes o traductores de software presentes durante la ejecucin. Estructuras de datos y constantes definidas por el usuario Debe de existir espacio disponible para las estructuras que fueron creadas o declaradas por el usuario, incluyendo las constantes. Puntos de regreso de subprogramas Puesto que estos tienen la propiedad de ser invocados desde cualquier parte del programa, debe reservarse memoria para el control de secuencia generada internamente, como los puntos de retornos de retorno de subprogramas. Entornos de referencia Conocidos como asociaciones de identificadores. Estos pueden requerir de una gran cantidad de espacio, por ejemplo una lista A en LISP (ms adelante se ver qu es una lista A).

Temporales en evaluacin de expresiones. Se requiere un espacio de almacenamiento temporal para los resultados intermedios de una evaluacin. Por ejemplo, en la evaluacin de la expresin (x + y) * (u + v), el resultado de la primera suma debe ser almacenado temporalmente mientras el resto de la evaluacin se completa. Temporales en el paso de parmetros Cuando un subprograma es llamado, una lista de los parmetros en turno debe de ser evaluada y los resultados almacenados temporalmente hasta que sea completada la evaluacin de la lista. Cuando la evaluacin de algn parmetro de la lista requiera llamadas a funciones recursivas, existe la posibilidad de que se emplee un nmero ilimitado de almacenamientos temporales sucesivos. Buffers de entrada y salida Los buffers sirven como reas de almacenamiento temporal donde los datos son almacenados durante el tiempo de transferencia fsica hacia el almacenamiento externo. Generalmente cientos de localidades son reservadas para los buffers. Datos miscelneos del sistema En casi todos los lenguajes, se requiere almacenamiento para diversos datos propios del sistema, por ejemplo tablas, estados de informacin para entrada y salida, as como para la recoleccin de basura y contadores de referencia. Adems de los elementos antes mencionados, es necesario considerar las principales operaciones que requieren almacenamiento en memoria: Llamadas a subprogramas y retorno de operaciones. Las llamadas a subprogramas, ambientes de referencia y otros datos utilizados en subprogramas son la mayora de operaciones que requieren almacenamiento. La ejecucin del retorno desde un subprograma usualmente requiere la liberacin del espacio de almacenamiento utilizado durante la ejecucin. Creacin y destruccin de operaciones de estructuras de datos. Si el lenguaje posee operaciones que permiten la creacin de nuevas estructuras de datos en puntos arbitrarios durante la ejecucin de un programa (no solamente cuando inicia algn subprograma), entonces estas operaciones normalmente requieren disponer de espacio aparte del utilizado cuando inicia el subprograma. Ejemplos de esto son las instrucciones new en pascal o malloc en C. Adems el lenguaje debe proveer una operacin explcita de destruccin como dispose en pascal o free en C. Insercin y borrado de operaciones de componentes Si el lenguaje proporciona operaciones de insercin y borrado de estructura de datos, para que estas operaciones puedan ser implementadas, se podra requerir de operaciones de almacenamiento y liberacin del espacio.

Almacenamiento controlado por el programador y por el sistema


Fases del manejo de almacenamiento

Hay tres aspectos bsicos del almacenamiento: Asignacin inicial Al principio de la ejecucin cada pieza de almacenamiento debe ser reservada para usarse o estar disponible. Si est libre inicialmente, debe de poder ser reservada dinmicamente durante la ejecucin del programa. Cualquier sistema de almacenamiento requiere de alguna tcnica para mantener un registro del espacio libre, as como mecanismos para su uso, dependiendo de las necesidades durante la ejecucin. Recuperacin El almacenamiento que ha sido asignado y usado subsecuentemente debera de ser recuperado por el administrador de almacenamiento para su nuevo uso. El proceso de recuperacin puede ser simple, como el reposicionamiento del apuntador de stack, o complejo, como la recuperacin de basura. Compactacin y nuevo uso. En el mejor de los casos, el espacio de almacenamiento recuperado podra estar inmediatamente listo para su nuevo uso. Otras veces podra ser necesaria la compactacin, que es la construccin de grandes bloques libres a partir de piezas pequeas de almacenamiento. El nuevo uso normalmente involucra las mismas tcnicas que la asignacin inicial.

Manejo de almacenamiento esttico


Es la forma ms sencilla de asignacin. El espacio reservado durante la traduccin del programa permanece fijo durante la ejecucin. Normalmente el almacenamiento para los segmentos de cdigo del usuario y del sistema es reservado estticamente. Tambin los buffers de I/O y datos miscelneos del sistema. La reservacin esttica no requiere de administracin de almacenamiento en tiempo de ejecucin, y por supuesto, tampoco recuperacin y nuevo uso. En varias implementaciones de Fortran toda la asignacin de memoria es reservada dinmicamente. Cada subprograma es compilado por separado, y el compilador determina el code segment (incluyendo un registro de activacin), las reas de datos, temporales, direccin del punto de retorno y componentes miscelneos del sistema. El loader reserva espacio en memoria para los bloques compilados y para rutinas de tiempos de corrida del sistema. Durante la ejecucin del programa no es necesario que algn mecanismo de administracin del almacenamiento tome lugar. El manejo de almacenamiento esttico es eficiente, ya que no se requiere de tiempo ni de espacio para la administracin de almacenamiento durante la ejecucin. Para muchos programas la asignacin esttica es bastante satisfactoria. Fortran est diseado para almacenamiento esttico.

Manejo de almacenamiento basado en stacks.


Es la forma ms simple de administracin de almacenamiento en tiempo de ejecucin. El espacio libre al inicio de la ejecucin consiste de un bloque secuencial en la memoria. Conforme nuevo espacio es solicitado, este es tomado de locaciones sucesivas de este bloque, comenzando por algn extremo. El espacio debe de ser liberado en orden inverso, para que el bloque de espacio liberado quede siempre en la parte alta del stack.

En este caso, todo lo que se necesita para el control del almacenamiento es un simple apuntador de stack (stack pointer). Este siempre apunta a la parte alta del stack, donde se localiza la siguiente palabra libre de almacenamiento. Todo el espacio usado yace debajo de la direccin sealada por el stack pointer. Cuando un bloque de k locaciones es requerido, el apuntador simplemente se mueve k locaciones ms adelante. Si un bloque de k locaciones es liberado, el apuntador se mueve k locaciones hacia abajo. Por esto, la compactacin de la memoria ocurre automticamente. Cuando un subprograma es llamado, un nuevo record es creado en el tope del stack. La mayora de las implementaciones de Pascal estn basadas en un stack central de registros de activacin de subprogramas, junto con un rea estticamente reservada que contiene los programas del sistema y los segmentos de cdigo de subprogramas. En la siguiente figura, en (a) se muestra la activacin tpica de un subprograma en Pascal. En (b) se muestra la organizacin de la memoria durante la ejecucin.

Organizacin de la memoria en Pascal

El uso del stack en LISP es algo diferente. Las llamadas a subprogramas (funciones) son estrictamente anidadas y un stack podra ser usada para mantener los registros de activacin. Cada registro de activacin contiene un punto de retorno y temporales para la evaluacin de expresiones y la transmisin de parmetros. Los ambientes de referencia locales podran ser tambin colocados en el mismo stack, pero el programador puede manipular estas asociaciones. Por lo tanto, normalmente estos son almacenados en un stack separado, representada como una lista ligada, llamada la A-lista. Una lista de memoria usada por LISP se muestra en la siguiente figura.

Organizacin de la memoria en LISP durante la ejecucin

La divisin del almacenamiento en un rea reservada estticamente, en otra rea reservada por un stack, y un rea reservada por un heap no solamente es utilizada por Pascal y LISP. Otros lenguajes como Ada, C y Prolog tambin hacen esta divisin tripartita de la memoria.

Administracin de almacenamiento por heap: Elementos de tamao fijo.


El tercer tipo de manejo de almacenamiento es el llamado almacenamiento por heap. Un heap es un bloque de almacenamiento con piezas que son asignadas y liberadas de una manera relativamente estructurada. Aqu los problemas de reservacin de espacio, recuperacin, compactacin y nuevo uso pueden ser difciles de resolver. La necesidad de utilizar un heap surge cuando un lenguaje permite almacenamiento para asignacin y liberacin en puntos arbitrarios durante la ejecucin de un programa. Por ejemplo en ML dos listas pueden concatenarse para la creacin de una tercera, o el programador puede definir dinmicamente un nuevo tipo de datos. Es conveniente dividir las tcnicas de administracin del almacenamiento en dos categoras, dependiendo de si los elementos que van a ser alojados son de tamao fijo o variable. Cuando los elementos son de tamao fijo, las tcnicas para el almacenamiento pueden ser simplificadas considerablemente. La compactacin no es un problema, pues todos los elementos disponibles tiene el mismo tamao. Supongamos que el espacio de cada elemento de tamao fijo es almacenado en el heap y despus liberado ocupa N palabras de la memoria. Generalmente N debe de ser 1 o 2. Suponiendo que el heap ocupa un bloques contiguos de la memoria, conceptualmente podemos dividirlo en una sucesin de K elementos, cada uno de longitud N, as que el tamao del heap es N*K. Inicialmente los K elementos estn ligados para formar una lista de espacio libre. Esto quiere decir que la primera palabra de cada elemento en la lista apunta a la primera palabra del siguiente elemento en la lista. Para reservar un elemento, el primer elemento en la lista de espacio libre es removido de la lista y su apuntador es retornado a la operacin que solicit el almacenamiento. Cuando un elemento es liberado, simplemente es ligado a la cabeza de la lista de espacio libre. En la siguiente figura se ilustra este proceso.

Estructura de la lista de espacio libre. Las reas sombreadas representan elementos que fueron reservados y no liberados

Recuperacin: Contadores de referencia y recoleccin de basura: La forma ms sencilla de recuperacin es la del retorno explcito. Cuando un elemento que estaba en uso est disponible para nuevo uso, este debe ser explcitamente identificado como free y retornado a la lista de espacio libre. Cuando los elementos son utilizados por el sistema, cada rutina del sistema es responsable de liberar el espacio. El retorno explcito es la tcnica natural para administrar el almacenamiento en el heap, pero desafortunadamente no siempre es posible emplearla. Hay dos viejos problemas que la inutizan: garbage y dangling references. dangling references: si una estructura se destruye antes de que todos los accesos a la estructura hayan sido destruidos, cualquier trayectoria restante se convierte en una referencia dangling. Garbage: si el ltimo acceso a la estructura es destruido sin que la estructura misma sea destruida, entonces la estructura se convierte en garbage. En el contexto de la administracin de almacenamiento en heap, una referencia dangling es un apuntador a un elemento que ha sido retornado a la lista de espacio libre, y cuyo espacio podra ser utilizado para cualquier otro propsito. Un elemento garbage es uno que est disponible para su nuevo uso, pero que como no se encuentra en la lista de espacio libre, se convierte en espacio inaccesible. Si la basura se acumula, el almacenamiento disponible es gradualmente reducido hasta que el programa no puede continuar su ejecucin por falta de espacio libre conocido. Las referencias dangling pueden causar un caos. Si un programa intenta modificar una estructura, que ha sido liberada, a travs de una referencia dangling, los contenidos de un elemento de la lista de espacio libre pueden ser modificados inadvertidamente. Si esta modificacin sobrescribe el apuntador que liga a este elemento con el siguiente

elemento libre de la lista, todo el resto de la lista podra volverse inaccesible. Peor an, un intento posterior para reservar espacio usando el apuntador de la lista en el elemento sobrescrito podra dar lugar a resultados impredecibles, por ejemplo, un pedazo de un programa ejecutable podra ser declarado como free space y luego modificado. El retorno explcito de heaps facilita la creacin de garbage y dangling references. Ejemplos en C: Garbage: int *p, *q; /* p y q son apuntadores a enteros */ ... p=malloc(sizeof(int)); /* se almacena un entero */ p = q; /* se pierde la direccin de p */ dangling: int *p, *q; ... p=malloc(sizeof(int)); q = p; free(p); /* p y q son apuntadores a enteros */ /* se almacena un entero */ /* se copia a q la direccin de p */ /* se libero el espacio apuntado por q */

El sistema enfrenta las mismas dificultades que el usuario. En LISP. Por ejemplo, las listas ligadas son un tipo de estructura de datos bsico. Una de las operaciones primitivas de LISP es cdr, la cual, dado un apuntador a un elemenrto en la lista ligada, retorna un apuntador al siguiente elemento de la lista. (Ver la siguiente figura)

Operacin cdr en LISP

El siguiente elemento al que fue originalmente apuntado podra haber sido ser liberado por la operacin cdr, si el nico apuntador hacia este es el determinado por cdr . Si cdr no retorna el elemento a la lista de espacio libre, este se convierte en basura. Sin embargo, si cdr manda el elemento a la lista de elementos libres y existen otros apuntadores hacia l, entonces estos apuntadores se convierten en dangling references. Si no existe una forma de determinar cuando estos otros apuntadores existen, entonces cdr se convierte en un generador potencial de garbage o de dangling references. Existen otras alternativas para la solucin de estos problemas en el retorno explicito, una es la de los reference counts y otra la de los garbage colectors. Reference counts. El uso de un contador de referencia genera un requerimiento mayor de espacio. El contador de referencia indica cuantos apuntadores a un elemento existen. Cuando un elemento es colocado en el espacio libre, su contador de referencia se inicializa en 1. Cuando un se crea un nuevo apuntador al elemento, el contador se incrementa en uno. Cuando ste apuntador es destruido, el contador de referencia se decrementa en uno. Cuando el contador de referencia de un elemento llega a cero, el elemento es libre y regresa a la lista de espacio libre. Los contadores de referencia permiten evitar las referencias dangling y a generacin de garbage en la mayora de los casos. Consideremos nuevamente la instruccin cdr de LISP. Si cada elemento de la lista contiene un un contador de referencias, entonces es simple para la operacin cdr evitar las

dificultades previas. cdr simplemente debe de substraer 1 del contador de referencias del elemento originalmente apuntado por su output. Cuando el programador utiliza la instruccin erase o free, el contador de referencia tambin provee proteccin a la informacin. Si se emplea la sentencia free, el contador de referencia se decrementa en 1. Si la cuenta llega a cero la estructura regresa a la lista de espacio libre; si por el contrario, el contador de referencia es mayor a cero, esto indica que la estructura sigue siendo accesible y entonces la sentencia free no tiene efecto. El principal problema se que genera al utilizar al contador de referencia es el costo que hay que pagar para mantenerlo. Dado que la accin de incrementar y decrementar es llevada a cabo continuamente, la eficiencia de la ejecucin disminuye. Supongamos, por ejemplo, que hay que asignar a un apuntador P, el valor de un apuntador Q: int *P, *Q; P=2; P=Q; Sin el contador de referencia solo era necesario copiar el valor de Q en P. Ahora se tienen que llevar a cabo varias tareas: 1. Acceder al elemento apuntado por P y decrementar su contador en 1. 2. Verificar el resultado de la operacin anterior. Si el resultado es cero, regresar la estructura al espacio libre. 3. Copiar la liga al valor apuntado por Q en P. 4. Acceder al elemento apuntado por Q e incrementar el contador de referencia por 1. Como se puede ver, esto incrementa substancialmente el costo de esta simple operacin. Cualquier operacin similar que pueda crear o destruir apuntadores debe de modificar los contadores de referencias tambin. Adems, existe un costo extra de almacenamiento para mantener los contadores de referencias. Sin embargo, esta tcnica es popular en los sistemas de procesamiento paralelo. Recoleccin de basura. El principal problema que genera la acumulacin de basura es la cantidad de espacio que queda inutilizable conforme la ejecucin del programa avanza. La filosofa del modelo de recoleccin de basura es simple: cuando el espacio libre es ocupado totalmente y es necesario ms espacio para almacenar, el cmputo se suspende temporalmente y un proceso de recoleccin de basura tiene lugar. Este identifica los elementos inservibles en la estructura y los regresa al espacio libre. Una vez liberado el espacio, el cmputo se reanuda y el proceso de recoleccin de basura no se vuelve a activar hasta que el espacio libre se haya agotado. El proceso de recoleccin de basura se lleva a cabo en dos fases: Marcado. En ste proceso cada elemento activo dentro de la estructura es marcado. Esta marca pone el bit del colector de basura en apagado.

Barrido. Mediante un proceso secuencial se examinan todos los elementos de la estructura, siendo mandados al espacio libre todos aquellos que posean encendido el bit de recoleccin de basura; al mismo tiempo que se lleva a cabo el barrido todos los elementos, sus bits de barrido son reestablecidos. La parte relativa al marcado es la ms difcil del proceso, debido a que como el espacio libre se encuentra agotado, cada elemento dentro de la estructura se encuentra activado, por tanto deber ser analizado en el proceso. Desafortunadamente, la revisin de cada elemento no puede arrojar como resultado si el elemento debe ser enviado al espacio libre o no, adems un apuntador de un elemento a otro dentro de nuestra estructura no precisa que ste elemento se encuentre activo. Para identificar los elementos que se encuentran activos, se buscan ligas que salgan de nuestra estructura, stos elementos se pueden considerar activos, adems de los que tengan ligas con elementos activos. Asignacin de almacenamiento en LISP La relacin entre el stack y el heap en LISP se muestra en la siguiente figura. En esta figura, se supone que: El almacenamiento en el heap contiene 15 elementos, de los cuales 9 estn actualmente en la lista de espacio libre. (a) Las definiciones siguientes han sido introducidas por el usuario: (defun f1(x y z) (cons x f2,y,z))) (defun f2(v w) (cons v w)) La ejecucin de la expresin (f1 a (b c) (d e)) tiene lugar como sigue: 1. Se invoca f1 y los argumentos x y z se agregan al stack usando las 9 entradas de heap disponibles en la lista de espacio libre (b) 2. Se invoca f2 con apuntadores a sus argumentos v y w (c) 3. La lista de espacio libre est vaca. El recolector de basura marca primero los elementos a los que se apunta desde el stack y luego, en un segundo paso, pone todos los elementos restantes en la lista de libres. (d) 4. Se calcula el valor de f2 y se pone en el stack (e) 5. Se calcula el valor de f1 y se pone en el stack (f). El sistema de LISP mostrara automticamente este resultado al usuario 6. Todos los elementos del cmputo son ahora basura. Cuando la lista libre vuelva a estar vaca, sern recuperados por la prxima recoleccin de basura.

Reservacin de espacio en el stack y en el heap para LISP Para realizar este proceso de marcado se asumen las siguientes caractersticas: 1. Ningn elemento activo deber ser alcanzado desde fuera de la estructura por un cambio de apuntadores. 2. Deber ser posible localizar cualquier apuntador externo que apunte hacia algn elemento de nuestra estructura.

3. Debe ser posible identificar cuando un elemento dentro de la estructura no tiene apuntadores procedentes de otro elemento dentro de la misma.

Administracin de almacenamiento por heap: Elementos de tamao variable


El manejo de estructuras de almacenamiento es complejo cuando los elementos que contienen estn conformados por estructuras de datos creadas por el usuario o registros de activacin. Este tipo de datos impiden que la memoria se maneje de una manera ordinaria y se deben aplicar tcnicas para recuperar el espacio libre dentro de las pginas de memoria para reutilizar este espacio. Almacenamiento inicial y nuevo uso Cuando los elementos guardados en la estructura de almacenamiento tienen un tamao fijo, el uso del espacio libre y el espacio ocupado se realiza con simples sumas a partir del apuntador inicial y el tamao de la pgina. En el caso de elementos de tamao variable la localizacin del espacio libre mediante sta tcnica no es posible. El objetivo es formar bloques libres lo ms grandes que sea posible. Para recuperar el espacio libre en stos casos se pueden emplear dos mtodos de nuevo uso de espacio: 1. Uso de espacio libre, buscando en la lista de localidades un bloque de tamao adecuado y devolviendo a la lista cualquier espacio sobrante despus de la reservacin. 2. Compactando el espacio libre moviendo todos los elementos activos al principio de la estructura de almacenamiento y dejando el espacio libre al final del stack. Nuevo uso directo mediante la lista de espacio libre Cuando una peticin de almacenamiento de N palabras se hace, existen dos formas para llevarla a cabo. En un mtodo normal se alojaran las N palabras y el resto sera enviado al espacio libre, sin embargo cuando se hace uso de una lista de espacio libre existen dos tcnicas para realizar sta operacin: 1. Mtodo del primero encontrado. Cuando un espacio de N palabras es necesitado, la lista de espacio libre es revisada hasta que un bloque de N palabras o ms palabras es encontrado, en ese momento se aloja la informacin y el resto del espacio es regresado a la lista de espacio libre. 2. Mtodo del mejor encontrado. Cuando un espacio de N palabras es requerido, la lista de espacio libre es revisada hasta encontrar un bloque del menor tamao que sea mayor o igual a N palabras. Este bloque es dividido en un bloque de N palabras y el resto del espacio es regresado a la lista de espacio libre. Este ltimo mtodo aunque optimiza el espacio de almacenamiento tiene una desventaja, la cul se refleja en el costo de recorrer toda la lista de espacio libre cada vez que se desea realizar un almacenamiento. Recobro de espacio con bloques de tamao variable. Antes de considerar el problema de la compactacin del espacio libre, es necesario hablar de las tcnicas con las que este es recuperado cuando se emplean bloques de tamao variable. Hay pocas diferencias con el caso en que se emplean bloques de tamao fijo. El retorno explcito del espacio a una lista de espacio libre es la tcnica ms simple, pero los problemas de garbage y dangling references se presentan nuevamente. El problema de la recoleccin de basura se presenta en la fase de barrido, en el cual el recolector de basura elimina todos los bloques marcados con el bit de barrido. Sin embargo en el caso de los bloques de tamao

variable no se puede determinar de una manera simple donde termina un bloque y donde comienza el siguiente. La solucin que se presenta es el uso de un indicador entero que marque el tamao del bloque, el cul se deber localizar despus del bit de barrido, y as la recoleccin de basura se podra llevar acabo mediante la lectura de esta informacin. Durante esta fase de verificacin se puede ejecutar una rutina de compactacin que permita mantener la mayor cantidad de bloques vacos juntos. Si combinamos sta tcnica de recoleccin de basura con una compactacin completa podremos eliminar el uso de las listas de espacio vaco, sustituyndolas por el uso de un solo apuntador al principio del espacio libre. Compactacin y el problema de la fragmentacin de memoria. Un problema con el que nos enfrentamos al emplear bloques de tamao variable es la fragmentacin de la memoria. Cuando se comienza el trabajo contamos con un gran bloque de espacio libre, sin embargo cuando continuamos trabajando, la memoria se fragmenta en pequeas piezas generadas por el almacenamiento y borrado de elementos. Al final de este proceso se da el caso de que no podemos alojar bloques de N palabras debido a que no tenemos suficiente espacio libre en forma consecutiva. Sin embargo, puede ocurrir que al contar el espacio libre que se tiene en la lista de espacio libre, podemos comprobar que hay mas espacio libre del que requerimos. Para solucionar este problema se emplea la compactacin de los bloques de memoria libres. Existen dos tipos de compactacin posibles: Compactacin parcial: Cuando los bloques activos no pueden ser movidos, solo los bloques adyacentes contenidos en la lista de espacio libre puede ser compactada. Compactacin total: Si los bloques activos en la estructura pueden ser movidos, todos los bloques activos son recorridos al inicio del stack de almacenamiento, dejando el espacio libre en el bloque final. La compactacin total requiere que cuando un bloque activo es movido, todos los apuntadores a ese bloque apunten ahora a la nueva localidad.