Con bloques de tamaño fijo, lo que ha descrito es una lista gratuita . Esta es una técnica muy común, con el siguiente giro: la lista de bloques libres se almacena en los bloques libres. En el código C, se vería así:
static void *alloc_ptr = START_OF_BIG_SEGMENT;
static void *free_list_head = NULL;
static void *
allocate(void)
{
void *x;
if (free_list_head == NULL) {
x = alloc_ptr;
alloc_ptr = (char *)alloc_ptr + SIZE_OF_BLOCK;
} else {
x = free_list_head;
free_list_head = *(void **)free_list_head;
}
return x;
}
static void
release(void *x)
{
*(void **)x = free_list_head;
free_list_head = x;
}
Esto funciona bien siempre que todos los bloques asignados tengan el mismo tamaño, y ese tamaño es un múltiplo del tamaño de un puntero, de modo que se conserva la alineación. La asignación y la desasignación son de tiempo constante (es decir, tan constante como el acceso a la memoria y las adiciones elementales; en una computadora moderna, el acceso a la memoria puede implicar errores de caché e incluso memoria virtual, por lo tanto, accesos al disco, por lo que el "tiempo constante" puede ser bastante grande) No hay sobrecarga de memoria (no hay punteros adicionales por bloque o cosas por el estilo; los bloques asignados son contiguos). Además, el puntero de asignación alcanza un punto dado solo si, en un momento, se tuvieron que asignar muchos bloques: dado que la asignación prefiere usar la lista libre, el puntero de asignación se incrementa solo si el espacio debajo del puntero actual está lleno de reloj. En ese sentido, técnica.
Decrecienteel puntero de asignación después de un lanzamiento puede ser más complejo, ya que los bloques libres se pueden identificar de manera confiable solo siguiendo la lista libre, que los revisa en un orden impredecible. Si es importante para usted reducir el tamaño del segmento grande cuando sea posible, puede usar una técnica alternativa, con más sobrecarga: entre dos bloques asignados, coloca un "agujero". Los agujeros están vinculados entre sí con una lista doblemente vinculada, en orden de memoria. Necesita un formato de datos para un agujero de manera que pueda localizar la dirección de inicio del agujero sabiendo dónde termina, y también el tamaño del agujero si sabe dónde comienza el agujero en la memoria. Luego, cuando liberas un bloque, creas un agujero que fusionas con el siguiente y el anterior, reconstruyendo (aún en tiempo constante) la lista ordenada de todos los agujeros. La sobrecarga es entonces de aproximadamente dos palabras de tamaño de puntero por bloque asignado; pero, a ese precio, puede detectar de manera confiable la aparición de un "agujero final", es decir, una ocasión para disminuir el tamaño del segmento grande.
Hay muchas variaciones posibles. Un buen artículo introductorio es Dynamic Storage Allocation: A Survey and Critical Review de Wilson et al.