it-swarm.com.de

Woher weiß free, wie viel es gibt?

In der C-Programmierung können Sie eine beliebige Art von Zeiger als Argument an free übergeben. Woher weiß es, wie groß der zugewiesene Speicher ist, der freigegeben werden soll? Immer wenn ich einen Zeiger auf eine Funktion übergebe, muss ich auch die Größe übergeben (dh ein Array von 10 Elementen muss 10 als Parameter erhalten, um die Größe des Arrays zu kennen), aber ich muss die Größe nicht an die übergeben freie Funktion. Warum nicht, und kann ich dieselbe Technik in meinen eigenen Funktionen verwenden, um zu vermeiden, dass ich um die zusätzliche Variable der Array-Länge karren muss?

347
Joshua Cheek

Wenn Sie malloc() aufrufen, geben Sie die zuzuweisende Speichermenge an. Die tatsächlich verwendete Speichermenge ist geringfügig höher und enthält zusätzliche Informationen, die (mindestens) angeben, wie groß der Block ist. Sie können (zuverlässig) nicht auf diese anderen Informationen zugreifen - und sollten es auch nicht :-).

Wenn Sie free() aufrufen, werden lediglich die zusätzlichen Informationen angezeigt, um herauszufinden, wie groß der Block ist.

318
Gary McGill

Die meisten Implementierungen von C-Speicherzuweisungsfunktionen speichern Abrechnungsinformationen für jeden Block entweder in der Zeile oder separat.

Ein typischer Weg (in-line) besteht darin, tatsächlich sowohl einen Header als auch den von Ihnen angeforderten Speicher zuzuweisen, der auf eine bestimmte Mindestgröße aufgefüllt ist. Wenn Sie beispielsweise nach 20 Bytes gefragt haben, weist das System möglicherweise einen 48-Byte-Block zu:

  • 16-Byte-Header mit Größe, Spezialmarker, Prüfsumme, Zeigern auf den nächsten/vorherigen Block und so weiter.
  • 32 Bytes Datenbereich (Ihre 20 Bytes werden zu einem Vielfachen von 16 aufgefüllt).

Die Adresse, die Sie dann erhalten, ist die Adresse des Datenbereichs. Wenn Sie dann den Block freigeben, nimmt free einfach die Adresse, die Sie ihm gegeben haben, und überprüft, sofern Sie diese Adresse oder den Speicher um sie herum nicht verstopft haben, die Kontoinformationen unmittelbar davor. Grafisch wäre das in etwa so:

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

Denken Sie daran, dass die Größe des Headers und das Auffüllen vollständig durch die Implementierung definiert sind (tatsächlich ist das Ganze durch die Implementierung definiert) (ein) Die Inline-Abrechnungsoption ist jedoch weit verbreitet.

Die in den Abrechnungsinformationen vorhandenen Prüfsummen und speziellen Markierungen sind häufig die Ursache für Fehler wie "Speicherbereich beschädigt" oder "Double Free", wenn Sie sie überschreiben oder zweimal freigeben.

Das Auffüllen (um die Zuweisung effizienter zu gestalten) ist der Grund, warum Sie manchmal ein wenig über das Ende Ihres angeforderten Speicherplatzes hinaus schreiben können, ohne Probleme zu verursachen (tun Sie das immer noch nicht, es ist undefiniertes Verhalten und, nur weil es manchmal funktioniert, nicht. ' Das heißt nicht, dass es in Ordnung ist, das zu tun.


(ein) Ich habe Implementierungen von malloc in eingebetteten Systemen geschrieben, in denen Sie 128 Byte erhalten haben, unabhängig davon, wonach Sie gefragt haben (das war die Größe der größten Struktur im System), vorausgesetzt, Sie haben 128 Byte oder weniger angefordert (Anforderungen) für mehr würde mit einem NULL-Rückgabewert getroffen werden). Eine sehr einfache Bitmaske (d. H. Nicht in Reihe) wurde verwendet, um zu entscheiden, ob ein 128-Byte-Block zugewiesen wurde oder nicht.

Andere, die ich entwickelt habe, hatten unterschiedliche Pools für 16-Byte-Chunks, 64-Byte-Chunks, 256-Byte-Chunks und 1-KB-Chunks. Auch hier wurde mithilfe einer Bitmaske entschieden, welche Blöcke verwendet wurden oder verfügbar waren.

Diese beiden Optionen haben es geschafft, den Overhead der Buchhaltungsinformationen zu reduzieren und die Geschwindigkeit von malloc und free zu erhöhen (keine Notwendigkeit, benachbarte Blöcke beim Freigeben zusammenzuführen), was in der Umgebung, in der wir arbeiteten, besonders wichtig ist im.

131
paxdiablo

Von dem comp.lang.c FAQ list: Woher weiß free, wie viele Bytes es gibt?

Die malloc/free-Implementierung merkt sich die Größe jedes Blocks bei der Zuweisung, sodass es nicht erforderlich ist, ihn beim Freigeben an die Größe zu erinnern. (Normalerweise wird die Größe neben dem zugewiesenen Block gespeichert, weshalb die Dinge normalerweise schlecht abbrechen, wenn die Grenzen des zugewiesenen Blocks sogar leicht überschritten werden.)

46
jdehaan

Diese Antwort wurde verschoben von Woher weiß free (), wie viel Speicher freigegeben werden muss? wo ich durch eine scheinbare doppelte Frage völlig daran gehindert wurde, zu antworten. Diese Antwort sollte dann für dieses Duplikat relevant sein:


Für den Fall von malloc speichert der Heap-Allokator eine Zuordnung des ursprünglich zurückgegebenen Zeigers zu relevanten Details, die später für free benötigt werden. Dies beinhaltet typischerweise das Speichern der Größe des Speicherbereichs in einer für den verwendeten Allokator relevanten Form, beispielsweise der Rohgröße, oder eines Knotens in einem Binärbaum, der zum Verfolgen von Allokationen verwendet wird, oder einer Anzahl von verwendeten "Speichereinheiten".

free schlägt nicht fehl, wenn Sie den Zeiger "umbenennen" oder auf irgendeine Weise duplizieren. Es wird jedoch nicht die Referenz gezählt und nur die erste free ist korrekt. Zusätzliche free sind "doppelte freie" Fehler.

Der Versuch, free einen Zeiger mit einem anderen Wert als dem von vorherigen malloc zurückgegebenen und noch nicht freigegebenen zu verwenden, ist ein Fehler. Es ist nicht möglich, Speicherbereiche, die von malloc zurückgegeben wurden, teilweise freizugeben.

6
Matt Joiner

Zugehörige Informationen GLib Bibliothek verfügt über Speicherzuweisungsfunktionen, die keine implizite Größe speichern - und dann übergeben Sie einfach den Parameter size an free. Dies kann einen Teil des Overheads eliminieren.

4
EFraim

malloc() und free() sind system-/compilerabhängig, daher ist es schwierig, eine bestimmte Antwort zu geben.

Weitere Informationen zu dieser anderen Frage .

3
LiraNuna

Die ursprüngliche Technik bestand darin, einen etwas größeren Block zuzuweisen und die Größe am Anfang zu speichern, und dann der Anwendung den Rest des Blogs zu geben. Der zusätzliche Speicherplatz enthält eine Größe und möglicherweise Verknüpfungen, um die freien Blöcke für die Wiederverwendung zusammenzufädeln.

Es gibt jedoch bestimmte Probleme mit diesen Tricks, wie z. B. schlechtes Cache- und Speicherverwaltungsverhalten. Die Verwendung des Arbeitsspeichers direkt im Block führt dazu, dass Dinge unnötig eingeblendet werden, und es entstehen schmutzige Seiten, die das Teilen und Kopieren beim Schreiben erschweren.

Eine fortgeschrittenere Technik besteht darin, ein separates Verzeichnis zu führen. Es wurden auch exotische Ansätze entwickelt, bei denen Speicherbereiche die gleiche Zweierpotenz verwenden.

Im Allgemeinen lautet die Antwort: Eine separate Datenstruktur wird zugewiesen, um den Status beizubehalten.

2
DigitalRoss

Der Heap-Manager hat die zum zugewiesenen Block gehörende Speichermenge irgendwo gespeichert, als Sie malloc aufgerufen haben.

Ich habe selbst nie eine implementiert, aber ich denke, der Speicher direkt vor dem zugewiesenen Block enthält möglicherweise die Metainformationen.

2
Timbo

Zur Beantwortung der zweiten Hälfte Ihrer Frage: Ja, das können Sie, und ein ziemlich verbreitetes Muster in C ist das folgende:

typedef struct {
    size_t numElements
    int elements[1]; /* but enough space malloced for numElements at runtime */
} IntArray_t;

#define SIZE 10
IntArray_t* myArray = malloc(sizeof(intArray_t) + SIZE * sizeof(int));
myArray->numElements = SIZE;
1
MSalters

Wenn wir malloc nennen, verbraucht es einfach mehr Byte von seiner Anforderung. Dieser Mehr-Byte-Verbrauch enthält Informationen wie Prüfsumme, Größe und andere zusätzliche Informationen. Wenn wir zu diesem Zeitpunkt kostenlos anrufen, gehen Sie direkt zu den zusätzlichen Informationen, in denen die Adresse und die Anzahl der freien Blöcke angegeben sind.

0
Varun Chhangani