Wie funktionieren malloc () und free ()?
Möchte ich wissen, wie malloc
und free
Arbeit.
int main() {
unsigned char *p = (unsigned char*)malloc(4*sizeof(unsigned char));
memset(p,0,4);
strcpy((char*)p,"abcdabcd"); //**deliberately storing 8bytes**
cout << p;
free(p); //Obvious Crash, but I need how it works and why crash.
cout << p;
return 0;
}
Ich wäre wirklich dankbar, wenn die Antwort ist in der Tiefe auf Speicher-Ebene, wenn es möglich ist.
InformationsquelleAutor der Frage mahesh | 2009-07-13
Du musst angemeldet sein, um einen Kommentar abzugeben.
OK, einige Antworten zu malloc wurden schon gepostet.
Interessanter Teil ist wie die freien arbeiten (und in diese Richtung, malloc kann auch besser verstanden).
In vielen malloc/free-Implementierungen, die frei macht, die normalerweise nicht wieder den Speicher für das Betriebssystem (oder zumindest nur in seltenen Fällen). Der Grund dafür ist, dass Sie Lücken in Ihrem Haufen, und so kann es passieren, dass Sie nur Schluss für den 2 oder 4 GB virtuellen Speicher mit Lücken. Dies sollte vermieden werden, da, sobald der virtuelle Speicher abgeschlossen ist, werden Sie in wirklich großen Schwierigkeiten. Der andere Grund ist, dass das OS kann nur mit Speicher-chunks sind von einer bestimmten Größe und Ausrichtung. Spezifisch: in der Regel das OS kann nur mit Blöcken, die der virtuelle Speicher-manager verarbeiten kann (in den meisten Fällen ein Vielfaches von 512 bytes, z.B. 4 KB).
So der Rückkehr 40 Bytes an, die das OS wird einfach nicht funktionieren. Also, was bedeutet frei?
Frei wird, legen Sie den memory-block in einen eigenen kostenlosen block-Liste. In der Regel hat es auch versucht, miteinander verschmelzen benachbarte Blöcke in den Adressraum. Der freie block Liste ist nur eine zirkuläre Liste von Speicher-chunks, die einige der administrativen Daten in der Anfang. Dies ist auch der Grund, warum die Verwaltung sehr kleiner Speicher, der Elemente mit dem standard-malloc/free ist nicht effizient. Jeder chunk-Speicher benötigt zusätzliche Daten und mit den kleineren Größen mehr Fragmentierung passiert.
Der frei-Liste ist auch der erste Ort, den malloc sieht, wenn ein neuer chunk-Speicher erforderlich ist. Es wird gescannt, bevor es fordert neuen Speicher vom Betriebssystem anzufordern. Wenn ein Block gefunden wird, das größer ist als der benötigte Speicher, es ist in zwei Teile gegliedert. Zurückgegeben an den Aufrufer, der andere ist zurück in die freie Liste.
Gibt es viele verschiedene Optimierungen, um dieses standard-Verhalten (zum Beispiel für kleine Stücke von Speicher). Aber da malloc und free sind, müssen so universal das standard-Verhalten ist immer der fallback, wenn die alternativen nicht brauchbar sind. Gibt es auch Optimierungen in der Handhabung der freie-Liste — zum Beispiel die Speicherung der chunks in Listen sortiert nach Größen. Aber alle Optimierungen haben auch Ihre eigenen Grenzen.
Warum Ihr code crash:
Der Grund ist, dass durch das schreiben von 9 chars (nicht zu vergessen die abschließenden null-byte) in einem Bereich dimensioniert ist für 4 chars, werden Sie wahrscheinlich überschreiben Sie die administrativen Daten gespeichert, die für ein weiteres Stück der Erinnerung, die sich "hinter" Ihr chunk-Daten (da diese Daten meist gespeichert "vor" der Speicher-chunks). Wenn kostenlos dann versucht, um Ihr Stück in die freie Liste, kann es durch berühren dieser administrativen Daten und daher stolpern über einen Zeiger überschrieben. Dadurch wird das system zum Absturz bringen.
Dies ist ein eher anmutiges Verhalten. Ich habe auch Situationen gesehen, wo ein außer Kontrolle geratenen Zeiger hat irgendwo überschrieben Daten in den Speicher-frei-Liste und das system nicht sofort Abstürzen, aber einige Unterprogramme später. Selbst in einem system mittlerer Komplexität können solche Probleme werden wirklich, wirklich schwer zu Debuggen! In einem Fall, den ich beteiligt war, hat es uns (eine größere Gruppe von Entwicklern) mehrere Tage zu finden, der Grund des Absturzes-denn es war in einer völlig anderen Lage als angegeben durch die Speicher-dump. Es ist wie eine Zeitbombe. Wissen Sie, Ihre nächste "freie" oder "malloc" Abstürzen, aber man weiß nicht warum!
Diese sind einige der schlimmsten C/C++ - Probleme und ein Grund, warum die Zeiger können so problematisch.
InformationsquelleAutor der Antwort Juergen
Als aluser sagt in dieser forum thread:
malloc() ist system/compiler-abhängig sind, also es ist schwer zu geben, eine spezifische Antwort. Im Grunde es ist aber nicht verfolgen, was Speicher reserviert und je nachdem, wie es tut, so dass Sie Ihre Anrufe auf die freien, könnte scheitern oder erfolgreich sein.
malloc() and free() don't work the same way on every O/S.
InformationsquelleAutor der Antwort joe
Eine Implementierung von malloc/free besitzt die folgenden:
InformationsquelleAutor der Antwort samoz
Speicherschutz hat page-Granularität erforderlich wäre, die kernel-Interaktion
Deinem Beispiel-code im wesentlichen fragt, warum das Beispiel-Programm nicht Falle, und die Antwort ist, dass der Speicher-Schutz ist ein kernel-feature und gilt nur für ganze Seiten, in der Erwägung, dass der memory-allocator ist ein Bibliotheks-feature, und es schafft .. ohne Durchsetzung .. beliebig großen Blöcken, die oft viel kleiner ist als die Seiten.
Speicher können nur entfernt werden, aus Ihrem Programm in Einheiten von Seiten, und selbst das ist unwahrscheinlich, zu beachten.
calloc(3) und malloc(3) haben die Interaktion mit dem kernel zu bekommen, Speicher, falls erforderlich. Aber die meisten Implementierungen von free(3) keine Rückgabe von Speicher auf dem kernel1Sie fügen Sie es einfach an einen freien Liste, dass calloc() und malloc (), die sich später um die Wiederverwendung der freigegebene Blöcke.
Selbst wenn ein free() wieder zurückkehren wollte den Arbeitsspeicher des Systems zu, müsste es mindestens einen zusammenhängenden, Seite Speicher, um den kernel, um tatsächlich schützen die region, so dass die Veröffentlichung einer small-block würde nur dazu führen, auf einen Schutz zu ändern, wenn es die letzten kleinen block in einer Seite.
Damit Ihr block ist es, das sitzen auf der freien Liste. Fast immer kann man darauf zugreifen und in der Nähe Speicher, gerade als ob es waren noch Mittel. C kompiliert direkt in den Maschinencode und ohne spezielle debugging-Vorkehrungen gibt es keine sanity-checks auf lädt und speichert. Nun, wenn Sie versuchen, Zugriff auf einen freien block, ist das Verhalten nicht definiert durch den standard, um nicht zu machen, unzumutbare Anforderungen an die Bibliothek die Hersteller. Wenn Sie versuchen, Zugriff auf freigegebenen Speicher oder meory außerhalb eines zugewiesenen Blocks, gibt es verschiedene Dinge, die schief gehen können:
Theorie der Bedienung
So, nach hinten arbeiten von Ihrem Beispiel die Allgemeine Theorie, malloc(3) wird Speicher vom kernel, wenn es Sie braucht, und in der Regel in Einheiten von Seiten. Diese Seiten sind unterteilt oder Konzern wie das Programm benötigt. Malloc und free zusammenarbeiten, um zu halten ein Verzeichnis. Sie verschmelzen benachbarter freier Blöcke, wenn möglich, damit Sie in die Lage, große Blöcke. Das Verzeichnis kann oder kann nicht bedeuten, mit Speicher freigegeben Blöcke bilden eine verkettete Liste. (Die alternative ist ein bisschen mehr shared-memory und paging-freundlich, und es beinhaltet das reservieren von Speicher, die speziell für das Verzeichnis.) Malloc und free wenig haben die Fähigkeit zur Durchsetzung der Zugriff auf die einzelnen Bausteine, auch wenn spezielle und optionale debugging-code kompiliert wird, in das Programm.
1 ist. Die Tatsache, dass nur sehr wenige Implementierungen von free() zu versuchen, um wieder Speicher für das system nicht unbedingt wegen des implementors nachlassen. Interaktion mit dem kernel ist viel langsamer als einfach Ausführung von library-code, und der nutzen wäre gering. Die meisten Programme haben eine "steady-state" oder die Erhöhung der memory-footprint, also die Zeit, die Analyse der heap-Suche für Mehrweg-Speicher wäre völlig verschwendet. Andere Gründe sind die Tatsache, dass die interne Fragmentierung macht Seite ausgerichtet Blöcke unwahrscheinlich, zu existieren, und es ist wahrscheinlich, dass wieder ein block wäre fragment-Blöcke auf beiden Seiten. Schließlich werden die wenigen Programme, die wieder große Mengen an Speicher sind wahrscheinlich zu umgehen, malloc() und einfach reservieren und gratis-Seiten sowieso.
InformationsquelleAutor der Antwort DigitalRoss
In der Theorie, malloc holt Speicher, die vom Betriebssystem für diese Anwendung. Jedoch, da Sie nur 4 bytes, und das Betriebssystem muss die Arbeit in Seiten (oft 4k), malloc funktioniert ein wenig mehr als das. Es dauert eine Seite zu, und stellt seine eigenen Informationen gibt, so kann es verfolgen, was Sie reserviert haben und befreit von dieser Seite aus.
Beim zuordnen von 4 bytes, zum Beispiel malloc gibt Sie einen Zeiger auf 4 bytes. Was Sie vielleicht nicht wissen, ist, dass der Speicher 8-12 bytes vor deine 4 bytes verwendet wird, die durch malloc, um eine Kette von all den Speicher, den Sie zugewiesen haben. Wenn Sie Anruf frei, er nimmt den Zeiger, der auf den Rücken, wo es ist Daten ist und funktioniert.
Wenn Sie freien Speicher, malloc nimmt, dass der Speicher-block aus der Kette,... und möglicherweise oder möglicherweise nicht zurück, dass der Speicher für das Betriebssystem. Wenn Sie es tut, als der Zugriff auf diesen Speicher wird wahrscheinlich scheitern, da das OS wird entfernt Ihre Berechtigungen für den Zugriff auf diesen Speicherort. Wenn malloc hält die Erinnerung ( weil es andere Dinge zugeteilt, die Seite oder für irgendwelche Optimierungen ), dann wird der Zugriff erfolgt, um zu arbeiten. Es ist immer noch falsch, aber es könnte funktionieren.
DISCLAIMER: Was ich beschrieb, ist eine gemeinsame Umsetzung von malloc, aber keineswegs die einzig mögliche.
InformationsquelleAutor der Antwort Chris Arguin
Es gibt eine Beispiel-Implementierung der
malloc()
undfree()
im Buch (Kernighan und Ritchie "Die Programmiersprache C"). Da musste man Fragen, haben Sie es nicht gelesen - gehen Sie her und Lesen Sie es, und kehrt um von euren sündigen wegen. 😀InformationsquelleAutor der Antwort Jonathan Leffler
Ihre strcpy Linie versuche zum speichern von 9 bytes, nicht 8, weil der NUL-terminator. Es ruft ein Undefiniertes Verhalten.
Dem Aufruf von free kann oder kann nicht Abstürzen. Der Speicher "nach" die 4 bytes von Ihrer Aufteilung kann für etwas anderes genutzt werden, die von Ihrem C-oder C++ - Implementierung. Wenn es für etwas anderes genutzt, dann kritzelte alle über Sie wird dazu führen, dass "etwas anderes" schief gehen, aber wenn es nicht verwendet wird, für etwas anderes, dann könnten Sie passieren, um mit ihm Weg. "Getting away with it" klingt gut, aber ist eigentlich schade, da es bedeutet, dass Ihr code wird angezeigt, zum laufen OK, aber auf eine Zukunft führen, die Sie möglicherweise nicht mit ihm Weg erhalten.
Mit einem debugging-style-Speicher-Zuweisung finden Sie möglicherweise, dass eine spezielle guard-Wert geschrieben wurde, und die freien Prüfungen für den Wert und Gerät in Panik, wenn es nicht gefunden.
Andernfalls könnten Sie feststellen, dass die nächste 5 bytes umfasst einen Teil eines link-Knotens Zugehörigkeit zu einigen anderen block des Speichers, die bisher nicht zugeordnet noch. Befreien Sie den block, könnte auch beteiligt, indem es eine Liste der verfügbaren Blöcke, und da haben Sie kritzelte in der Liste, Knoten, dass der Betrieb konnte dereferenzieren einen Zeiger mit einem ungültigen Wert, zu einem Absturz führen.
Es hängt alles von der memory allocator - verschiedene Implementierungen verwenden unterschiedliche Mechanismen.
InformationsquelleAutor der Antwort Steve Jessop
Wie malloc() und free() funktioniert, hängt von der Laufzeit-Bibliothek verwendet. In der Regel, malloc() reserviert einen heap (a block of memory) aus dem Betriebssystem. Jede Anfrage malloc (), dann weist Sie ein kleines Stück von diesem Speicher werden die Rückgabe eines Zeigers an den Aufrufer. Die memory-allocation-Routinen speichern, einige zusätzliche Informationen über den block an Speicher, in der Lage sein zu verfolgen, belegten und freien Speicher auf dem heap. Diese Informationen sind oft gespeichert in ein paar bytes, kurz bevor der Zeiger zurückgegeben, die von malloc() und es kann eine verknüpfte Liste von Speicher-Blöcken.
Durch das schreiben über das blockieren des Arbeitsspeichers durch malloc() werden Sie die meisten wahrscheinlich zerstören einige der Buchführung Daten des nächsten Blocks, die möglicherweise die verbleibenden ungenutzten Speicherblock.
Einen Ort, wo du das Programm kann auch Abstürzen, wenn Sie zu viele Zeichen in den Puffer. Wenn die zusätzlichen Zeichen befinden sich außerhalb des heap, erhalten Sie möglicherweise eine Zugriffsverletzung, wie Sie versuchen zu schreiben, um nicht vorhandene Speicher.
InformationsquelleAutor der Antwort Martin Liversage
Dies hat nichts speziell zu tun mit malloc und free. Ihr Programm weist ein Undefiniertes Verhalten nach dem kopieren der string - es könnte Abstürzen an diesem Punkt oder zu irgendeinem Zeitpunkt danach. Dies ist true, selbst wenn Sie nie benutzt malloc und free, und zwar das char-array auf dem stack oder statisch.
InformationsquelleAutor der Antwort
malloc und free sind implementierungsabhängig. Eine typische Implementierung umfasst die Partitionierung verfügbare Speicher in eine "freie Liste" - eine verlinkte Liste der verfügbaren Speicher-Blöcke. Viele Implementierungen künstlich teilen Sie es in kleine vs große Objekte. Freie Blöcke beginnen mit Informationen darüber, wie groß der Speicherblock ist und wo der nächste ist, etc.
Wenn Sie malloc ein block gezogen wird, von der freien Liste. Wenn Sie frei ist, wird der block wieder in die freie Liste. Chancen sind, wenn Sie überschreiben das Ende des Mauszeigers, Sie sind schriftlich auf dem Kopf der einen block in der frei-Liste. Wenn du deine Speicher, free() versucht, auf den nächsten block, und wahrscheinlich landet der Kollision mit einem Zeiger, der bewirkt, dass ein bus-Fehler.
InformationsquelleAutor der Antwort plinth
Nun hängt es von der Speicher-Zuweisung Umsetzung und die OS.
Unter windows zum Beispiel kann ein Prozess Fragen Sie nach einer Seite oder mehr RAM. Das OS weist dann diese Seiten in den Prozess. Dies ist jedoch nicht zugewiesenen Speicher für Ihre Anwendung. Die CRT-memory-allocator wird den Speicher als einen zusammenhängenden "verfügbar" - block. Die CRT-Speicher-Zuweisung läuft dann über die Liste der freien Blöcke und finden Sie die kleinsten möglichen block, dass Sie es verwenden können. Es wird dann so viel, dass der block, wie es braucht, und fügen Sie es zu einem "reserviert" - Liste. An den Kopf der tatsächliche Speicher-Allokation wird ein header. Dieser header enthält verschiedene bit von Informationen (es könnte zum Beispiel, enthalten Sie die nächsten und vorherigen zugewiesenen Blöcke bilden eine verkettete Liste. Es wird wahrscheinlich enthalten die Größe der Zuweisung).
Frei wird, dann entfernen Sie die Kopfzeile, und fügen Sie es wieder das Kostenlose memory-Liste. Wenn es bildet sich ein größerer block mit den umliegenden frei-Blöcke werden diese addiert, zu einem größeren block. Wenn eine ganze Seite ist jetzt frei, die Zuweisung wird, höchstwahrscheinlich, wieder die Seite, auf der OS.
Es ist nicht ein einfaches problem. Die OS-Zuweisung Teil ist völlig außerhalb Ihrer Kontrolle. Ich empfehle Ihnen, Lesen Sie über so etwas wie Doug Lea ' s Malloc (DLMalloc), um ein Verständnis dafür, wie relativ schnell-Zuweisung funktioniert.
Edit: Dein Absturz wird verursacht durch die Tatsache, dass durch das schreiben, die größer als die Zuordnung, die Sie überschrieben haben den nächsten header Speicher. Auf diese Weise, wenn es befreit, es wird sehr verwirrt, was genau es ist, frei ' Ing und wie Sie verschmelzen in den folgenden block. Dies kann nicht immer zu einem Absturz sofort auf die Kostenlose. Es kann einen Absturz verursachen später. Im Allgemeinen vermeiden Sie Speicher überschreibt!
InformationsquelleAutor der Antwort Goz
Ihr Programm abstürzt, weil es verwendet Speicher, die nicht zu dir gehören. Es kann von jemand anderem verwendet werden oder nicht - wenn Sie Glück haben, Sie Abstürzen, wenn das problem nicht kann verborgen bleiben, für eine lange Zeit und kommen zurück und beißen Sie später.
Soweit malloc/free-Implementierung geht - ganze Bücher widmen sich dem Thema. Grundsätzlich ist die Zuweisung bekommen würde größere Speicherbereiche vom OS und verwalten diese für Sie aus. Einige der Probleme, die eine Zuweisung muss die Adresse lauten:
...
InformationsquelleAutor der Antwort devdimi
Es ist schwer zu sagen, weil das tatsächliche Verhalten unterscheidet sich zwischen den verschiedenen Compilern/- Laufzeiten. Sogar die debug/release-builds haben anderes Verhalten. Debug-builds von VS2005 einfügen Marker zwischen den Zuordnungen zu erkennen, Speicherbeschädigung, so dass anstelle von einem crash, es wird behaupten in free().
InformationsquelleAutor der Antwort Sebastiaan M
Es ist auch wichtig zu erkennen, dass Sie einfach durch das Programm Pause Zeiger, um mit
brk
undsbrk
eigentlich nicht reservieren den Speicher, es setzt lediglich die Adresse Platz. Unter Linux, zum Beispiel, der Speicher wird "gestützt" durch die tatsächlichen physischen Seiten, wenn dieser Adressbereich zugegriffen wird, wird die eine Seite Schuld, und wird schließlich führen zu den kernel-Aufruf in die Seite-Zuweisung zu bekommen, die als backing-Seite.InformationsquelleAutor der Antwort mgalgs