la fonction malloc de la mise en œuvre?
Je suis en train de mettre en œuvre malloc
et free
pour le C, et je ne suis pas sûr de la façon de réutiliser la mémoire. J'ai actuellement un struct
qui ressemble à ceci:
typedef struct _mem_dictionary {
void *addr;
size_t size;
int freed;
} mem_dictionary;
Mon malloc
ressemble à ceci:
void *malloc(size_t size) {
void *return_ptr = sbrk(size);
if (dictionary == NULL)
dictionary = sbrk(1024 * sizeof(mem_dictionary));
dictionary[dictionary_ct].addr = return_ptr;
dictionary[dictionary_ct].size = size;
dictionary[dictionary_ct].freed = 1;
dictionary_ct++;
return return_ptr;
}
Quand j'ai de la mémoire libre, je voudrais juste marquer l'adresse 0
(qui indique que c'est gratuit). Dans mon malloc
, je puis utiliser une boucle for pour rechercher une valeur dans le tableau de l'égalité des 0
, et ensuite d'allouer de la mémoire à cette adresse. Je suis un peu confus comment le mettre en œuvre.
- Il y a un bel article sur dlmalloc ici: g.oswego.edu/dl/html/malloc.html
Vous devez vous connecter pour publier un commentaire.
La façon la plus simple de le faire est de garder une liste chaînée de blocs. Dans
malloc
, si la liste n'est pas vide, vous recherchez un bloc assez grand pour satisfaire la demande et le retourner. Si la liste est vide ou si un tel bloc peut être trouvé, vous appelezsbrk
d'allouer de la mémoire à partir du système d'exploitation. dansfree
, il vous suffit d'ajouter de la mémoire de morceau à la liste de bloc libre. En bonus, vous pouvez essayer de fusionner contiguë bloc libéré, et vous pouvez modifier la stratégie pour le choix du bloc de retour (premier ajustement, ajustement optimal, ...). Vous pouvez également choisir de partager la bloquer si elle est plus grande que la demande.Quelques exemples de mise en œuvre (il n'est pas testé et il est évidemment pas thread-safe, utilisez à vos risques et périls):
Remarque:
(n + align_to - 1) & ~ (align_to - 1)
est une astuce pour arrondirn
au plus proche multiple dealign_to
qui est plus grande quen
. Cela ne fonctionne que lorsquealign_to
est une puissance de deux et dépend de la représentation binaire des nombres.Quand
align_to
est une puissance de deux, il n'a qu'un ensemble de bits, et doncalign_to - 1
a tous le bit de poids faible de jeux (ie.align_to
est de la forme 010 000......0, etalign_to - 1
est de la forme000...001...1
). Cela signifie que~ (align_to - 1)
a l'ensemble de la haute ensemble de bits, et de la faible peu unset (ie. il est de la forme111...110...0
). Doncx & ~ (align_to - 1)
sera mis à zéro tous les les bits de poids faible dex
et autour d'elle jusqu'à la plus proche multiple dealign_to
.Enfin, l'ajout de
align_to - 1
àsize
de nous assurer de round-up au plus proche multiple dealign_to
(saufsize
est déjà un multiple dealign_to
dans ce cas, nous voulons obtenirsize
).(size + sizeof(size_t))
au plus proche multiple dealign_to
qui est plus grande que(size + sizeof(size_t))
. Cela ne fonctionne que sialign_to
est une puissance de deux.Vous ne souhaitez pas définir la
size
champ de l'entrée du dictionnaire de zéro, vous aurez besoin de cette information pour les ré-utiliser. Au lieu de cela, définirfreed=1
uniquement lorsque le bloc est libéré.Vous ne pouvez pas fusionner deux blocs adjacents, car il peut y avoir intervenant appels à
sbrk()
, de sorte que rend cela plus facile. Vous avez juste besoin d'unfor
boucle qui recherche un assez grand bloc libéré:Ce n'est pas un grand
malloc()
mise en œuvre. En fait, la plupart desmalloc
/free
implémentations d'allouer un petit en-tête de chaque bloc retourné par malloc. L'en-tête peut débuter à l'adresse de huit (8) octets moins que le pointeur retourné, par exemple. Dans ces octets que vous pouvez stocker un pointeur vers lemem_dictionary
entrée de posséder le bloc. Cela évite de O(N) opérations enfree
. Vous pouvez éviter le O(N) dansmalloc()
par la mise en œuvre d'une file d'attente de priorité de blocs libérés. Envisager l'utilisation d'un binôme tas, avec une taille de bloc que l'index.malloc
. Il a au moins un défaut évident: il ne peut jamais être supérieure à 1024 blocs attribués à un moment donné. Le seul but de donner cet exemple est de donner au lecteur un point de départ pour la mise en œuvre de leurs propresmalloc
. C'est juste une base conceptuelle pour la mise en œuvre d'unmalloc
/free
de la bibliothèque. Il ne prend même pas la mettre en œuvrerealloc
une insuffisance éclatante. Il pourrait même ne pas être le meilleur exemple. 🙂Je suis d'emprunt code de Sylvain réponse. Il semble avoir manqué le calcul de la taille de la free_block* ini calcul de la surcharge.
Dans l'ensemble du code en ajoutant cette free_block comme en-tête de la mémoire allouée.
1. Lorsque l'utilisateur appelle la fonction malloc, malloc renvoie l'adresse de la charge utile, juste après cet en-tête.
2. quand free est appelé, l'adresse de départ de l'en-tête du bloc est calculée (en soustrayant la taille d'en-tête à partir du bloc d'adresse, et qui est ajouté au bloc libre de la piscine.
free_block** head = &(free_block_list_head.next);
) Je ne le vois pas être utilisé n'importe où. En outre, pourquoi le faisons-nous ajoutersizeof(free_block)
avant de revenir?head
est un pointeur vers une adresse contenant un pointeur. Il est utilisé dans la boucle permettant de dissocier le bloc de mémoire est retourné à l'utilisateur. L'addition et la soustractionsizeof(free_block)
est une commune et astuce pour "masquer" les métadonnées de l'appelant.free(NULL)
sera erreur de segmentation.realloc
fonction de cette mise en œuvre?