OK, einige Antworten zu malloc wurden bereits veröffentlicht.
Der interessantere Teil ist, wie frei funktioniert (und in dieser Richtung kann auch Malloc besser verstanden werden).
In vielen malloc / free-Implementierungen gibt free normalerweise den Speicher nicht an das Betriebssystem zurück (oder zumindest nur in seltenen Fällen). Der Grund ist, dass Sie Lücken in Ihrem Heap bekommen und es daher vorkommen kann, dass Sie nur Ihre 2 oder 4 GB virtuellen Speicher mit Lücken fertigstellen. Dies sollte vermieden werden, da Sie, sobald der virtuelle Speicher fertig ist, in große Schwierigkeiten geraten. Der andere Grund ist, dass das Betriebssystem nur Speicherblöcke verarbeiten kann, die eine bestimmte Größe und Ausrichtung haben. Um genau zu sein: Normalerweise kann das Betriebssystem nur Blöcke verarbeiten, die der virtuelle Speichermanager verarbeiten kann (meistens Vielfache von 512 Bytes, z. B. 4 KB).
Die Rückgabe von 40 Bytes an das Betriebssystem funktioniert also einfach nicht. Was macht Free?
Free setzt den Speicherblock in eine eigene freie Blockliste. Normalerweise wird auch versucht, benachbarte Blöcke im Adressraum miteinander zu verschmelzen. Die freie Blockliste ist nur eine kreisförmige Liste von Speicherblöcken, die am Anfang einige Verwaltungsdaten enthalten. Dies ist auch der Grund, warum die Verwaltung sehr kleiner Speicherelemente mit dem Standard malloc / free nicht effizient ist. Jeder Speicherblock benötigt zusätzliche Daten und bei kleineren Größen tritt eine stärkere Fragmentierung auf.
Die freie Liste ist auch der erste Ort, den Malloc betrachtet, wenn ein neuer Speicherblock benötigt wird. Es wird gescannt, bevor es neuen Speicher vom Betriebssystem anfordert. Wenn ein Block gefunden wird, der größer als der benötigte Speicher ist, wird er in zwei Teile geteilt. Einer wird an den Anrufer zurückgegeben, der andere wird wieder in die kostenlose Liste aufgenommen.
Es gibt viele verschiedene Optimierungen für dieses Standardverhalten (z. B. für kleine Speicherblöcke). Aber da malloc und free so universell sein müssen, ist das Standardverhalten immer der Fallback, wenn Alternativen nicht verwendbar sind. Es gibt auch Optimierungen bei der Handhabung der freien Liste - zum Beispiel das Speichern der Chunks in Listen, die nach Größen sortiert sind. Alle Optimierungen haben aber auch ihre eigenen Grenzen.
Warum stürzt Ihr Code ab:
Der Grund dafür ist, dass Sie durch Schreiben von 9 Zeichen (vergessen Sie nicht das nachfolgende Null-Byte) in einen Bereich mit einer Größe von 4 Zeichen wahrscheinlich die Verwaltungsdaten überschreiben, die für einen anderen Speicherblock gespeichert sind, der sich "hinter" Ihrem Datenblock befindet ( da diese Daten meistens "vor" den Speicherblöcken gespeichert werden). Wenn free dann versucht, Ihren Chunk in die freie Liste aufzunehmen, kann es diese Verwaltungsdaten berühren und daher über einen überschriebenen Zeiger stolpern. Dies wird das System zum Absturz bringen.
Dies ist ein ziemlich anmutiges Verhalten. Ich habe auch Situationen gesehen, in denen ein außer Kontrolle geratener Zeiger irgendwo Daten in der speicherfreien Liste überschrieben hat und das System nicht sofort abstürzte, sondern einige Unterprogramme später. Selbst in einem System mittlerer Komplexität können solche Probleme sehr, sehr schwer zu debuggen sein! In dem einen Fall, in dem ich involviert war, haben wir (eine größere Gruppe von Entwicklern) mehrere Tage gebraucht, um den Grund für den Absturz zu finden - da er sich an einem völlig anderen Ort befand als dem, der durch den Speicherauszug angegeben wurde. Es ist wie eine Zeitbombe. Sie wissen, Ihr nächstes "freies" oder "malloc" wird abstürzen, aber Sie wissen nicht warum!
Dies sind einige der schlimmsten C / C ++ - Probleme und ein Grund, warum Zeiger so problematisch sein können.