OK, quelques réponses sur malloc ont déjà été publiées.
La partie la plus intéressante est le fonctionnement de la gratuité (et dans ce sens, malloc aussi peut être mieux compris).
Dans de nombreuses implémentations 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 obtiendrez des lacunes dans votre tas et donc cela peut arriver, que vous venez de terminer vos 2 ou 4 Go de mémoire virtuelle avec des lacunes. Cela devrait être évité, car dès que la mémoire virtuelle sera terminée, vous aurez de très gros ennuis. L'autre raison est que le système d'exploitation ne peut gérer que des blocs de mémoire d'une taille et d'un alignement spécifiques. Pour être 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 4 Ko).
Donc, retourner 40 octets au système d'exploitation ne fonctionnera tout simplement pas. Alors, que fait le libre?
Free placera le bloc de mémoire dans sa propre liste de blocs libres. Normalement, il essaie également de fusionner les blocs adjacents dans l'espace d'adressage. La liste de blocage libre n'est qu'une liste circulaire de blocs de mémoire qui contiennent au début des données administratives. C'est aussi la raison pour laquelle la gestion de très petits éléments de mémoire avec le malloc / free standard n'est pas efficace. Chaque bloc de mémoire a besoin de données supplémentaires et avec des tailles plus petites, une plus grande fragmentation se produit.
La liste libre est également le premier endroit que malloc examine lorsqu'un nouveau morceau de mémoire est nécessaire. Il est analysé avant d'appeler une nouvelle mémoire du système d'exploitation. Lorsqu'un bloc est plus grand que la mémoire requise, il est divisé en deux parties. L'un est renvoyé à l'appelant, l'autre est remis dans la liste gratuite.
Il existe de nombreuses optimisations différentes de ce comportement standard (par exemple pour les petits morceaux de mémoire). Mais comme malloc et free doivent être si universels, le comportement standard est toujours le repli lorsque les alternatives ne sont pas utilisables. Il existe également des optimisations dans la gestion de la liste libre - par exemple, le stockage des morceaux dans des listes triées par tailles. Mais toutes les optimisations ont également leurs propres limites.
Pourquoi votre code plante-t-il:
La raison en est qu'en écrivant 9 caractères (n'oubliez pas l'octet nul final) dans une zone de 4 caractères, vous écraserez probablement les données administratives stockées pour un autre bloc de mémoire qui se trouve "derrière" votre bloc de données ( car ces données sont le plus souvent stockées "devant" les morceaux de mémoire). Lorsqu'il est libre, puis essaie de mettre votre morceau dans la liste gratuite, il peut 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 le système n'a pas immédiatement planté, mais certains sous-programmes 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'étais impliqué, il nous a fallu (à un plus grand groupe de développeurs) plusieurs jours pour trouver la raison de l'accident - car il était dans un emplacement totalement différent de celui indiqué par le vidage de la mémoire. C'est comme une bombe à retardement. Vous savez, votre prochain "gratuit" ou "malloc" va planter, mais vous ne savez pas pourquoi!
Ce sont certains des pires problèmes C / C ++, et l'une des raisons pour lesquelles les pointeurs peuvent être si problématiques.