Comment faire sans et de malloc en C?
Je suis à essayer de comprendre ce qui serait arrivé si j'essaie de libérer un pointeur "du milieu"
regardez, par exemple, le code suivant:
char *ptr = (char*)malloc(10*sizeof(char));
for (char i=0 ; i<10 ; ++i)
{
ptr[i] = i+10;
}
++ptr;
++ptr;
++ptr;
++ptr;
free(ptr);
- Je obtenir une collision avec une exception non Gérée msg d'erreur.
Je veux comprendre pourquoi et comment les œuvres libres, de sorte que je ne sais pas seulement la façon de l'utiliser, mais aussi être en mesure de comprendre des erreurs étranges et les exceptions et mieux déboguer mon codeץ
Merci beaucoup
- Il n'y a pas de singulier "Comment ça marche" parce que c'est la mise en œuvre spécifique.
- Attention, @GMan, il y a une réelle différence entre la mise en œuvre définies (ce qui signifie la mise en œuvre doit documenter et d'agir en conformité avec ce qui est) et indéfinis (ce qui signifie que tout peut arriver, jusqu'à et y compris les singes volant de votre bout). 🙂
- Je voulais dire "Comment free() travail", pas "qu'est Ce que mon code?" J'ai été de répondre à la question titre.
- Toutes mes excuses, mal compris la réponse.
- Peut-être vous obtiendrez les gens avec la volonté de l'UB questions pour mieux écouter si vous avez mentionné que les singes puissent voler dans au lieu de simplement voler.. 😉
- double possible de Comment faire des malloc() et free() fonctionne?
- Excusez-moi?
Vous devez vous connecter pour publier un commentaire.
Lorsque vous malloc un bloc, il alloue un peu plus de mémoire que vous avez demandé. Cette mémoire supplémentaire est utilisé pour stocker des informations telles que la taille du bloc alloué, et un lien à l'autre libre/bloc utilisé dans une chaîne de blocs, et parfois certains "protection des données" qui permet au système de détecter si vous écrivez après la fin de votre bloc alloué. Aussi, la plupart des allocateurs sera arrondir le total de la taille et/ou le début de votre partie de la mémoire à un multiple d'octets (par exemple, sur un système 64 bits, il peut aligner les données à un multiple de 64 bits (8 octets) accès aux données à partir des non-alignés adresses peut être plus difficile et inefficace pour le processeur/bus), de sorte que vous pouvez également retrouver avec des "padding" (les octets non utilisés).
Lorsque vous libérer de votre pointeur, il utilise cette adresse pour trouver l'information spéciale, il a ajouté au début (normalement) de votre bloc alloué. Si vous passez à une autre adresse, elle aura accès à la mémoire qui contient les ordures, et donc son comportement est indéfini (mais qui le plus souvent va entraîner une panne)
Plus tard, si vous le free() le bloc, mais de ne pas "oublier" le pointeur de votre souris, vous pouvez accidentellement essayez d'accéder aux données à travers le pointeur dans l'avenir, et le comportement est indéfini. L'une des situations suivantes peut se produire:
C'est pourquoi il est important de vous assurer de ne pas utiliser un pointeur lors de la libération de la mémoire, c'points à la meilleure pratique consiste à définir le pointeur à NULL après la libération de la mémoire, parce que vous pouvez facilement tester la valeur NULL, et de tenter d'accéder à la mémoire par l'intermédiaire d'un pointeur NULL, va provoquer un mauvais, mais cohérente comportement, ce qui est beaucoup plus facile à déboguer.
Vous savez probablement que vous êtes censé passer exactement le pointeur que vous avez reçu.
Parce que free() n'est pas d'abord de savoir de quelle taille est votre bloc est, il a besoin d'informations supplémentaires afin d'identifier le bloc d'origine à partir de son adresse et de revenir ensuite à une liste libre. Il tentera également de fusionner les petites libéré des blocs avec les voisins afin de produire une plus précieux grand bloc libre.
En fin de compte, l'allocation doit avoir des métadonnées sur votre bloc, à un minimum, il sera nécessaire d'avoir stocké la longueur de quelque part.
Je vais décrire trois façons de le faire.
Un endroit évident serait de stocker juste avant de le pointeur retourné. Il pourrait allouer un bloc de quelques octets de plus que ce qui est demandé, magasin de la taille dans le premier mot, puis de retour pour vous un pointeur vers le deuxième mot.
Une autre façon serait de garder une carte distincte décrivant au moins la longueur de blocs alloués, à l'aide de l'adresse comme une clé.
Une mise en œuvre pourrait tirer des informations à partir de l'adresse et une carte. Le noyau BSD 4.3 allocateur (qui s'appelait, je crois, le "McKusick-Karel allocateur") rend la puissance de deux allocations pour les objets de moins de la taille de la page et ne conserve que par la taille de page, en faisant toutes les allocations à partir d'une page donnée, d'une taille unique.
Il serait possible avec certains types de la deuxième et probablement n'importe quelle sorte de troisième type de l'allocation pour vraiment détecter que vous avez avancé le pointeur et DTRT, bien que je doute que toute la mise en œuvre de brûler le moteur d'exécution pour le faire.
La plupart (si pas tous) de la mise en œuvre sera la recherche de la quantité de données afin de libérer de quelques octets avant le pointeur de la manipulation.
Faire un sauvage
free
conduira à la mémoire de la carte de la corruption.Si votre exemple, lorsque vous allouez 10 octets de mémoire, le système de réserve, disons, 14. Le premier 4 contient la quantité de données que vous avez demandé (10), puis la valeur de retour de la
malloc
est un pointeur vers le premier octet de données non utilisés dans le 14 alloué.Lorsque vous appelez
free
sur ce pointeur, le système de recherche de 4 octets en arrière pour savoir qu'il allouée à l'origine de 14 octets pour qu'il sache combien gratuit. Ce système vous empêche de fournir la quantité de données pour libérer comme un paramètre supplémentaire àfree
lui-même.Bien sûr, d'autres de la mise en œuvre de
malloc
/free
pouvez choisir la façon d'atteindre cet objectif. Mais ils n'ont généralement pas de soutien àfree
sur un pointeur différent de ce qui a été renvoyé parmalloc
ou fonction équivalente.De http://opengroup.org/onlinepubs/007908775/xsh/free.html
C'est un comportement indéterminé - ne pas le faire. Seulement
free()
pointeurs obtenus à partir demalloc()
, ne réglez jamais avant que.Le problème est
free()
doit être très rapide, de sorte qu'il n'essaie pas de trouver l'attribution de votre ajusté appartient l'adresse, mais qui tente de retourner le bloc exactement le réglage de l'adresse du segment de mémoire. Qui conduit à un comportement indéterminé - généralement de corruption de segment ou de blocage du programme.Vous êtes à la libération de la mauvaise adresse. En changeant la valeur de ptr, vous modifiez l'adresse. free n'a aucun moyen de savoir qu'il devrait essayer de libérer un bloc à 4 octets de retour. Gardez le pointeur d'origine intact et qu'au lieu de le manipulé un seul. Comme d'autres l'ont souligné, les résultats de ce que vous faites sont "undefined"... d'où l'exception non gérée.
Ne jamais faire cela.
Vous êtes à la libération de la mauvaise adresse. En changeant la valeur de ptr, vous modifiez l'adresse. free n'a aucun moyen de savoir qu'il devrait essayer de libérer un bloc à 4 octets de retour. Gardez le pointeur d'origine intact et qu'au lieu de le manipulé un seul. Comme d'autres l'ont souligné, les résultats de ce que vous faites sont "undefined"... d'où l'exception non gérée
Tiré du livre: Comprendre et Utiliser C les Pointeurs