Avec des blocs de taille fixe, ce que vous avez décrit est une liste gratuite . C'est une technique très courante, avec la torsion suivante: la liste des blocs libres est stockée dans les blocs libres eux-mêmes. En code C, cela ressemblerait à ceci:
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;
}
Cela fonctionne bien tant que tous les blocs alloués ont la même taille et que cette taille est un multiple de la taille d'un pointeur, de sorte que l'alignement est préservé. L'allocation et la désallocation sont à temps constant (c'est-à-dire aussi à temps constant que les accès à la mémoire et les ajouts élémentaires - dans un ordinateur moderne, un accès à la mémoire peut impliquer des échecs de cache et même de la mémoire virtuelle, donc des accès au disque, donc le "temps constant" peut être assez gros). Il n'y a pas de surcharge de mémoire (pas de pointeurs par bloc supplémentaires ou des choses comme ça; les blocs alloués sont contigus). De plus, le pointeur d'allocation n'atteint un point donné que si, à un moment donné, de nombreux blocs ont dû être alloués: puisque l'allocation préfère utiliser la liste libre, le pointeur d'allocation n'est augmenté que si l'espace sous le pointeur actuel est plein d'horloge. Dans ce sens, technique.
Décroissantle pointeur d'allocation après une version peut être plus complexe, car les blocs libres ne peuvent être identifiés de manière fiable qu'en suivant la liste gratuite, qui les parcourt dans un ordre imprévisible. S'il est important pour vous de réduire la grande taille des segments, vous pouvez utiliser une technique alternative, avec plus de surcharge: entre deux blocs alloués, vous mettez un "trou". Les trous sont liés ensemble avec une liste doublement liée, dans l'ordre de la mémoire. Vous avez besoin d'un format de données pour un trou de sorte que vous puissiez localiser l'adresse de début du trou en sachant où il se termine, ainsi que la taille du trou si vous savez où le trou commence en mémoire. Ensuite, lorsque vous libérez un bloc, vous créez un trou que vous fusionnez avec le trou suivant et le trou précédent, reconstruisant (toujours en temps constant) la liste ordonnée de tous les trous. La surcharge est alors d'environ deux mots de la taille d'un pointeur par bloc alloué; mais, à ce prix, vous pouvez détecter de manière fiable l'occurrence d'un "trou final", c'est-à-dire une occasion de diminuer la taille du grand segment.
Il existe de nombreuses variantes possibles. Un bon document d'introduction est Dynamic Storage Allocation: A Survey and Critical Review par Wilson et al.