Écriture d'un allocateur de mémoire
Extrait pour un allocateur de mémoire en C
Allocateurs de mémoire 101 - Écrivez un allocateur de mémoire simple
void * malloc ( size_t size );
void free ( void * ptr );
Block * merge_blocks ( Block * block );
// the above three will be implemented first later calloc and realloc Définissez la structure des données : vous aurez besoin d'une structure de données pour garder une trace de la taille et de l'état d'allocation de chaque bloc. Cela pourrait être une structure simple avec une taille et un drapeau indiquant si le bloc est libre ou non.
Initialisez le tas : lorsque votre programme commencera, vous devrez réserver un morceau de mémoire pour agir comme votre tas. Cela peut être fait en utilisant l'appel système mmap() .
Implémentez malloc() : Cette fonction doit trouver un bloc gratuit suffisamment grand pour satisfaire la demande. S'il n'existe pas de tel bloc, il devrait augmenter la taille du tas. Une fois qu'un bloc approprié est trouvé, il doit être marqué comme alloué et son adresse est retournée.
Implémentez free() : Cette fonction doit prendre un pointeur vers un bloc de mémoire, le marquer comme libre et potentiellement réduire la taille du tas si le bloc libéré est à la fin.
Implémentez realloc() : Cette fonction doit redimensionner un bloc alloué. Cela pourrait impliquer de trouver un nouveau bloc et de copier les anciennes données.
Gandage Fragmentation : Au fil du temps, le tas peut se fragmenter avec des blocs libres dispersés partout. Vous voudrez peut-être mettre en œuvre une stratégie pour défragmenter le tas, comme la fusion de blocs libres adjacents.
Dans le contexte d'un allocateur de tas, les "blocs" se réfèrent à des morceaux de mémoire dans le tas. Voici pourquoi vous en avez besoin et comment ils fonctionnent:
Pourquoi les blocs? : Lorsque vous gérez de la mémoire, il est utile de le diviser en morceaux gérables ou des "blocs". Chaque bloc peut être alloué et traité indépendamment. Cela permet une utilisation efficace de la mémoire, car vous pouvez allouer exactement autant de mémoire que vous en avez besoin, ni plus ni moins.
Structure du bloc : chaque bloc contient généralement des métadonnées autour du bloc (comme sa taille et si elle est gratuite ou allouée) et les données réelles stockées dans le bloc. Les métadonnées sont utilisées par l'allocateur pour gérer la mémoire.
Attribution : Lorsque vous appelez malloc() , l'allocateur recherche un bloc gratuit suffisamment grand pour contenir la quantité de données demandée. S'il en trouve un, il marque ce bloc comme alloué et renvoie un pointeur à la partie de données du bloc.
Deallocation : Lorsque vous appelez free() , l'allocateur marque le bloc comme gratuit, ce qui le rend disponible pour les allocations futures. Si le bloc libéré est à la fin du tas, l'allocateur peut également réduire la taille du tas pour libérer la mémoire.
Fragmentation : Au fil du temps, car les blocs sont alloués et traités, le tas peut se fragmenter. Cela signifie que la mémoire libre est divisée en petits blocs non contigus. Cela peut rendre difficile la recherche d'un bloc suffisamment grand pour un appel malloc() , même s'il y a suffisamment de mémoire libre totale. Pour gérer cela, les allocateurs incluent souvent la logique pour défragmenter le tas, comme la fusion de blocs libres adjacents.