OK, certaines réponses concernant malloc ont déjà été postées.
La partie la plus intéressante est comment fonctionne free (et dans cette direction, malloc aussi peut être mieux compris).
Dans de nombreuses implémentations de malloc/free, free ne renvoie normalement pas la mémoire au système d'exploitation (ou du moins seulement dans de rares cas). La raison en est que vous aurez des vides dans votre tas et qu'il peut donc arriver que vous finissiez vos 2 ou 4 Go de mémoire virtuelle avec des vides. Il faut éviter cela, car dès que la mémoire virtuelle est terminée, vous aurez de gros problèmes. L'autre raison est que le système d'exploitation ne peut gérer que des morceaux de mémoire d'une taille et d'un alignement spécifiques. Pour être plus précis : Normalement, le système d'exploitation ne peut gérer que les blocs que le gestionnaire de mémoire virtuelle peut gérer (le plus souvent des multiples de 512 octets, par exemple 4KB).
Ainsi, renvoyer 40 octets au système d'exploitation ne fonctionnera pas. Alors que fait free ?
Free placera le bloc mémoire dans sa propre liste de blocs libres. Normalement, il essaie également de réunir les blocs adjacents dans l'espace d'adressage. La liste des blocs libres n'est qu'une liste circulaire de morceaux de mémoire qui contiennent des données administratives au début. C'est aussi la raison pour laquelle la gestion de très petits éléments de mémoire avec le standard malloc/free n'est pas efficace. Chaque morceau de mémoire a besoin de données supplémentaires et plus la taille est petite, plus la fragmentation est importante.
La liste libre est également le premier endroit que malloc consulte lorsqu'un nouveau morceau de mémoire est nécessaire. Elle est parcourue avant de demander de la mémoire au système d'exploitation. Lorsqu'un morceau est trouvé qui est plus grand que la mémoire nécessaire, il est divisé en deux parties. L'une est renvoyée à l'appelant, l'autre est remise dans la liste libre.
Il existe de nombreuses optimisations différentes de ce comportement standard (par exemple pour les petits morceaux de mémoire). Mais puisque malloc et free doivent être si universels, le comportement standard est toujours la solution de repli lorsque les alternatives ne sont pas utilisables. Il y a aussi des optimisations dans la gestion de la free-list - par exemple en stockant les morceaux dans des listes triées par tailles. Mais toutes les optimisations ont aussi leurs propres limites.
Pourquoi votre code se plante :
La raison est qu'en écrivant 9 caractères (n'oubliez pas l'octet nul de fin) dans une zone dimensionnée pour 4 caractères, vous allez probablement écraser les données administratives stockées pour un autre morceau de mémoire qui se trouve "derrière" votre morceau de données (puisque ces données sont le plus souvent stockées "devant" les morceaux de mémoire). Lorsque free essaiera ensuite de placer votre bloc dans la liste libre, il pourra toucher ces données administratives et donc trébucher sur un pointeur écrasé. Cela fera planter le système.
C'est un comportement plutôt gracieux. J'ai également vu des situations où un pointeur en fuite quelque part a écrasé des données dans la liste sans mémoire et où le système n'a pas planté immédiatement mais quelques sous-routines plus tard. Même dans un système de complexité moyenne, de tels problèmes peuvent être vraiment, vraiment difficiles à déboguer ! Dans le cas où j'ai été impliqué, il nous a fallu (un groupe plus important de développeurs) plusieurs jours pour trouver la raison du plantage -- car il se trouvait à un endroit totalement différent de celui indiqué par le vidage de la mémoire. C'est comme une bombe à retardement. Vous savez que votre prochain "free" ou "malloc" va planter, mais vous ne savez pas pourquoi !
Ce sont là certains des pires problèmes du C/C++, et l'une des raisons pour lesquelles les pointeurs peuvent être si problématiques.
5 votes
Ne devrait-il pas en fait dépendre du compilateur et de la bibliothèque d'exécution utilisés ?
9 votes
Cela dépendra de l'implémentation du CRT. Vous ne pouvez donc pas le généraliser.
0 votes
Il y a un exemple d'implémentation de
malloc()
yfree()
dans Le Livre (Kernighan et Ritchie) " Le langage de programmation C "). Puisque vous avez dû le demander, vous ne l'avez pas lu - allez-y, lisez-le, et repentez-vous de vos péchés. :D60 votes
Que strcpy écrit 9 octets, et non 8. N'oubliez pas le terminateur NULL ;-).
0 votes
Cet article porte sur FORTRAN en réalité, mais les mêmes idées s'appliquent à C et C++ : stromberg.dnsalias.org/~strombrg/checking-early.html . L'article traite de certaines des choses qui peuvent mal tourner lorsque vous écrivez dans une région de mémoire non définie.
0 votes
Quelle section, quelle page ?
0 votes
@KorayTugay : Dans la 1ère édition, c'est aux pages 173-177. Dans la 2e édition, il se trouve aux pages 185-189. Dans les deux éditions, c'est la dernière section du dernier chapitre, juste avant l'annexe A, le manuel de référence.
4 votes
Ne lancez pas le résultat de
malloc
en C2 votes
@LuuVinhPhúc c'est du C++. Notez le
cout <<
0 votes
Ce code ne se bloque pas du tout, à moins que l'optimisation ne soit activée dans votre Makefile ou votre compilateur.
0 votes
Suppression de plus de quatre octets, ce qui fait que votre programme se plante.