509 Stimmen

Woher weiß free, wie viel free zu geben ist?

In der C-Programmierung können Sie jede Art von Zeiger als Argument an free übergeben. Woher weiß er, wie groß der Speicher ist, der freigegeben werden soll? Immer wenn ich einen Zeiger an eine Funktion übergebe, muss ich auch die Größe übergeben (d.h. ein Array mit 10 Elementen muss 10 als Parameter erhalten, um die Größe des Arrays zu kennen), aber ich muss die Größe nicht an die free-Funktion übergeben. Warum nicht, und kann ich dieselbe Technik in meinen eigenen Funktionen verwenden, damit ich nicht die zusätzliche Variable für die Länge des Arrays mit mir herumschleppen muss?

458voto

Gary McGill Punkte 25122

Wenn Sie anrufen malloc() geben Sie die Menge des zuzuweisenden Speichers an. Die tatsächlich verwendete Speichermenge ist etwas größer als diese und enthält zusätzliche Informationen, die (zumindest) die Größe des Blocks aufzeichnen. Auf diese anderen Informationen können Sie nicht (zuverlässig) zugreifen - und das sollten Sie auch nicht :-).

Wenn Sie anrufen free() Wenn Sie das Programm nicht verwenden, wird einfach anhand der zusätzlichen Informationen ermittelt, wie groß der Block ist.

198voto

paxdiablo Punkte 809679

Die meisten Implementierungen von C-Speicherzuweisungsfunktionen speichern Buchhaltungsinformationen für jeden Block, entweder in-line oder separat.

Eine typische Methode (in-line) besteht darin, sowohl einen Header als auch den angeforderten Speicher zuzuweisen, der auf eine bestimmte Mindestgröße aufgefüllt wird. Wenn Sie also beispielsweise 20 Byte angefordert haben, kann das System einen 48-Byte-Block zuweisen:

  • 16-Byte-Header mit Größe, spezieller Markierung, Prüfsumme, Verweis auf den nächsten/vorherigen Block usw.
  • 32 Bytes Datenbereich (Ihre 20 Bytes werden auf ein Vielfaches von 16 aufgefüllt).

Die Adresse, die Sie dann erhalten, ist die Adresse des Datenbereichs. Wenn Sie dann den Block freigeben, free nimmt einfach die Adresse, die Sie ihm geben, und prüft - vorausgesetzt, Sie haben diese Adresse oder den Speicher um sie herum nicht vollgestopft - die Buchhaltungsinformationen unmittelbar davor. Grafisch würde das in etwa so aussehen:

 ____ The allocated block ____
/                             \
+--------+--------------------+
| Header | Your data area ... |
+--------+--------------------+
          ^
          |
          +-- The address you are given

Denken Sie daran, dass die Größe des Headers und des Paddings vollständig durch die Implementierung definiert sind (eigentlich ist das ganze Ding durch die Implementierung definiert (a) aber die Option der Inline-Abrechnung ist eine gängige Option).

Die Prüfsummen und speziellen Markierungen, die in den Buchhaltungsinformationen vorhanden sind, sind oft die Ursache für Fehler wie "Memory arena corrupted" oder "Double free", wenn Sie sie überschreiben oder zweimal freigeben.

Das Auffüllen (um die Zuteilung effizienter zu machen) ist der Grund, warum man manchmal etwas über das Ende des angeforderten Platzes hinaus schreiben kann, ohne Probleme zu verursachen (trotzdem sollte man das nicht tun, es ist ein undefiniertes Verhalten, und nur weil es manchmal funktioniert, bedeutet das nicht, dass es in Ordnung ist, es zu tun).


(a) Ich habe Implementierungen geschrieben von malloc in eingebetteten Systemen, wo man 128 Bytes erhielt, egal was man verlangte (das war die Größe der größten Struktur im System), vorausgesetzt, man verlangte 128 Bytes oder weniger (Anfragen nach mehr würden mit einem NULL-Rückgabewert beantwortet). Eine sehr einfache Bit-Maske (d.h. nicht in-line) wurde verwendet, um zu entscheiden, ob ein 128-Byte-Block zugewiesen wurde oder nicht.

Andere, die ich entwickelt habe, hatten verschiedene Pools für 16-Byte-Blöcke, 64-Byte-Blöcke, 256-Byte-Blöcke und 1K-Blöcke, wobei wiederum eine Bitmaske verwendet wurde, um zu entscheiden, welche Blöcke verwendet wurden oder verfügbar waren.

Mit diesen beiden Optionen konnte der Aufwand für die Buchhaltungsinformationen verringert und die Geschwindigkeit der malloc y free (keine Notwendigkeit, benachbarte Blöcke beim Freigeben zusammenzulegen), was in der Umgebung, in der wir gearbeitet haben, besonders wichtig war.

52voto

jdehaan Punkte 19398

より comp.lang.c FAQ-Liste: Woher weiß free, wie viele Bytes es freigeben muss?

Die malloc/free-Implementierung merkt sich die Größe eines jeden Blocks, wenn er alloziert wird, so dass es nicht notwendig ist, ihn beim Freigeben an die Größe zu erinnern. (Normalerweise wird die Größe neben dem zugewiesenen Block gespeichert, weshalb es normalerweise zu Problemen kommt, wenn die Grenzen des zugewiesenen Blocks auch nur leicht überschritten werden)

9voto

Matt Joiner Punkte 105454

Diese Antwort wird verlegt von Woher weiß free(), wie viel Speicher es freigeben muss? wo ich durch eine scheinbar doppelte Frage abrupt an der Beantwortung gehindert wurde. Diese Antwort sollte dann für dieses Duplikat relevant sein:


Für den Fall, dass malloc speichert der Heap Allocator eine Zuordnung des ursprünglich zurückgegebenen Zeigers zu den relevanten Details, die für free den Speicher später zu löschen. Dazu gehört in der Regel die Speicherung der Größe des Speicherbereichs in einer für den verwendeten Allokator relevanten Form, z. B. als Rohgröße, als Knoten in einem Binärbaum zur Verfolgung von Zuweisungen oder als Anzahl der verwendeten Speicher-"Einheiten".

free schlägt nicht fehl, wenn Sie den Zeiger "umbenennen" oder ihn in irgendeiner Weise duplizieren. Er wird jedoch nicht als Referenz gezählt, und nur der erste free richtig sein wird. Zusätzlich free s sind "doppelt freie" Fehler.

Der Versuch, die free jeder Zeiger mit einem anderen Wert als dem, der von früheren malloc s, und noch nicht befreit ist ein Fehler. Es ist nicht möglich, Speicherbereiche teilweise freizugeben, die von malloc .

4voto

EFraim Punkte 12426

In diesem Zusammenhang sei angemerkt GLib Bibliothek hat Speicherzuweisungsfunktionen, die die implizite Größe nicht speichern - und dann übergeben Sie einfach den Parameter size an free. Dies kann einen Teil des Overheads eliminieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X