Woher weiß frei, wie viel freizugeben ist?

Lesezeit: 7 Minuten

Benutzeravatar von Joshua Cheek
Joshua Wange

In der C-Programmierung können Sie jeden beliebigen Zeiger als Argument an free übergeben, woher weiß er die Größe des zugewiesenen Speichers, der freigegeben werden soll? Immer wenn ich einen Zeiger an eine Funktion übergebe, muss ich auch die Größe übergeben (dh 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 übergeben freie Funktion. Warum nicht, und kann ich dieselbe Technik in meinen eigenen Funktionen verwenden, damit ich nicht die zusätzliche Variable der Länge des Arrays herumschleppen muss?

  • Eine ähnliche Frage: stackoverflow.com/questions/851958/… (obwohl ich sagen würde, dass es nicht ganz doppelt ist)

    – John Carter

    5. Oktober 2009 um 11:34 Uhr

  • Das Freunde-System ist eine andere Möglichkeit, dies basierend auf dem Zeiger ohne Overhead in jedem Block herauszufinden.

    – EvilTeach

    9. März 2014 um 16:34 Uhr


  • Dieser Beitrag erklärt es gut: stackoverflow.com/questions/1957099/…

    – Zeeshan

    2. Dezember 2016 um 7:23 Uhr

Benutzeravatar von Gary McGill
Gary McGill

Wenn du anrufst malloc(), geben Sie die zuzuweisende Speichermenge an. Die tatsächlich verwendete Speichermenge ist etwas größer und enthält zusätzliche Informationen, die (mindestens) aufzeichnen, wie groß der Block ist. Auf diese anderen Informationen können Sie nicht (zuverlässig) zugreifen – und das sollten Sie auch nicht :-).

Wenn du anrufst free()sieht es sich einfach die zusätzlichen Informationen an, um herauszufinden, wie groß der Block ist.

  • FYI, zum Beispiel BSD hat malloc_size() um zuverlässig auf die Blockgröße von an zuzugreifen malloc()ed-Zeiger. Aber es gibt keinen zuverlässigen, tragbaren Weg.

    – laalto

    5. Oktober 2009 um 7:53 Uhr

  • Ich denke, es ist wichtig zu sagen, dass dieser zusätzliche Informationsblock vor dem zurückgegebenen Zeiger liegt.

    – Georg Scholly

    5. Oktober 2009 um 8:28 Uhr

  • @gs Nun, das ist implementierungsabhängig. Aber ja, das ist normalerweise so.

    – Falaina

    5. Oktober 2009 um 11:20 Uhr

  • Können Sie sich den Horror vorstellen, wenn free() erforderte, dass der Programmierer genau angab, wie groß die malloc() Block war? Die Speicherlecks sind so schon schlimm genug.

    – MusiGenesis

    7. April 2010 um 13:45 Uhr

  • Warum sind diese Informationen verfügbar für malloc() und free(), aber Sie müssen die Größe eines Arrays speichern? Warum sollten sie es nicht möglich machen, so etwas zu tun blockSize(ptr) ob sie die Informationen trotzdem speichern?

    – corsiKa

    14. Juni 2014 um 1:12 Uhr

Benutzeravatar von paxdiablo
paxdiablo

Die meisten Implementierungen von C-Speicherzuweisungsfunktionen speichern Abrechnungsinformationen für jeden Block, entweder inline oder separat.

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

  • 16-Byte-Header, der Größe, spezielle Markierung, Prüfsumme, Zeiger auf den nächsten/vorherigen Block und so weiter enthält.
  • 32 Bytes Datenbereich (Ihre 20 Bytes aufgefüllt auf ein Vielfaches von 16).

Die Ihnen dann mitgeteilte Adresse 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 Abrechnungsinformationen 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 Padding vollständig implementierungsdefiniert sind (eigentlich ist das Ganze implementierungsdefiniert (a) aber die Inline-Abrechnungsoption ist üblich).

Die in den Accounting-Informationen vorhandenen Prüfsummen und Sonderzeichen sind häufig die Ursache für Fehler wie „Memory Arena beschädigt“ oder „Doppelt frei“, wenn man sie überschreibt oder doppelt freigibt.

Das Auffüllen (um die Zuordnung effizienter zu gestalten) ist der Grund, warum Sie manchmal etwas über das Ende des angeforderten Bereichs hinaus schreiben können, ohne Probleme zu verursachen (tun Sie das trotzdem nicht, es ist ein undefiniertes Verhalten und, nur weil es manchmal funktioniert, nicht t meine, es ist in Ordnung, es zu tun).


(a) Ich habe Implementierungen von geschrieben malloc in eingebetteten Systemen, in denen Sie 128 Bytes erhalten haben, egal was Sie angefordert haben (das war die Größe der größten Struktur im System), vorausgesetzt, Sie haben 128 Bytes oder weniger angefordert (Anforderungen nach mehr würden mit einem NULL-Rückgabewert beantwortet). Eine sehr einfache Bitmaske (dh nicht in Reihe) wurde verwendet, um zu entscheiden, ob ein 128-Byte-Chunk zugewiesen wurde oder nicht.

Andere, die ich entwickelt habe, hatten unterschiedliche 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 oder verfügbar waren.

Beide Optionen haben es geschafft, den Overhead der Abrechnungsinformationen zu reduzieren und die Geschwindigkeit zu erhöhen malloc und free (keine Notwendigkeit, benachbarte Blöcke beim Freigeben zusammenzuführen), besonders wichtig in der Umgebung, in der wir gearbeitet haben.

  • @paxdiablo Bedeutet das, dass malloc keine zusammenhängenden Speicherblöcke zuweist?

    – Benutzer10678

    5. November 2017 um 8:20 Uhr

  • @ user10678, die einzige wirkliche Anforderung von malloc ist, dass es Ihnen für den erfolgreichen Fall einen Speicherblock gibt, der mindestens so groß ist wie das, wonach Sie gefragt haben. Einzelne Blöcke sind in Bezug darauf, wie Sie auf Elemente in ihnen zugreifen, zusammenhängend, aber es ist nicht erforderlich, dass die Arenen, aus denen die Blöcke stammen, zusammenhängend sind.

    – paxdiablo

    5. November 2017 um 8:29 Uhr

  • Verwandte Frage: Warum gibt es keine Variante von malloc/free, bei der Sie die Größe beim Freigeben angeben und die Größe nicht speichern muss?

    – Benutzer253751

    4. Dezember 2019 um 14:57 Uhr

  • @ user253751, denn dann gibt es einen mehr Sache, die Sie über den Zeiger selbst hinaus im Auge behalten müssen. Es ist beides unnötig und gefährlich: void *x = malloc(200); free(x, 500); ist nicht wird gut enden 🙂 Auf jeden Fall für die Effizienz, das tatsächlich Größe des Puffers kann größer sein (darauf können Sie sich einfach nicht verlassen).

    – paxdiablo

    5. Dezember 2019 um 2:30 Uhr


  • @paxdiablo Es vermeidet auch die Verschwendung von Speicher, um die Größe zu halten.

    – Benutzer253751

    5. Dezember 2019 um 10:15 Uhr

Benutzeravatar von jdehaan
jdehaan

Von dem comp.lang.c FAQ-Liste: Woher weiß Free, wie viele Bytes freizugeben sind?

Die malloc/free-Implementierung merkt sich die Größe jedes Blocks, wenn er zugewiesen wird, daher ist es nicht notwendig, ihn beim Freigeben an die Größe zu erinnern. (Normalerweise wird die Größe neben dem zugewiesenen Block gespeichert, weshalb die Dinge normalerweise schlecht brechen, wenn die Grenzen des zugewiesenen Blocks auch nur geringfügig überschritten werden.)

  • Dies ist eine Nicht-Antwort. Die Frage ist genau diese: Warum kann Free zuverlässig die Größe des Blocks nachschlagen, aber dem Programmierer steht dafür keine Funktion zur Verfügung?

    – Banane

    4. Januar 2019 um 11:54 Uhr

  • Dies ist in der Tat ein Implementierungsdetail für die malloc-API, und es gibt keine API, um diese Informationen auf standardmäßige Weise zurückzugeben (meines Wissens). Das “System” zeichnet es auf und verwendet es weiter free. Vielleicht befriedigt Sie die Antwort nicht, aber ich glaube nicht, dass Sie eine mit allgemeineren Informationen erhalten werden 🙂

    – jdehaan

    20. Januar 2019 um 18:32 Uhr

Benutzeravatar von Matt Joiner
Matt Tischler

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


Für den Fall von mallocspeichert der Heap-Zuordner eine Abbildung des ursprünglich zurückgegebenen Zeigers auf relevante Details, die für benötigt werden freedie Erinnerung später. Dies umfasst typischerweise das Speichern der Größe des Speicherbereichs in irgendeiner Form, die für den verwendeten Zuordner relevant ist, beispielsweise die Rohgröße oder ein Knoten in einem binären Baum, der zum Verfolgen von Zuweisungen verwendet wird, oder eine Anzahl von verwendeten Speicher-“Einheiten”.

free wird nicht fehlschlagen, wenn Sie den Zeiger “umbenennen” oder ihn auf irgendeine Weise duplizieren. Es wird jedoch keine Referenz gezählt, sondern nur die erste free wird richtig sein. Zusätzlich frees sind “double free”-Fehler.

Versuchen free jeder Zeiger mit einem Wert, der sich von demjenigen unterscheidet, der von previous zurückgegeben wurde mallocs, und noch unfreigegeben ist ein Fehler. Es ist nicht möglich, Speicherbereiche, aus denen zurückgegeben wird, teilweise freizugeben malloc.

In einer verwandten Anmerkung GLib Die Bibliothek verfügt über Speicherzuweisungsfunktionen, die keine implizite Größe speichern – und dann übergeben Sie einfach den Größenparameter an free. Dadurch kann ein Teil des Overheads eliminiert werden.

Benutzeravatar von Timbo
Timbo

Der Heap-Manager hat die Speichermenge, die zu dem zugewiesenen Block gehört, irgendwo gespeichert, als Sie ihn aufgerufen haben malloc.

Ich habe selbst nie einen implementiert, aber ich vermute, dass der Speicher direkt vor dem zugewiesenen Block die Metainformationen enthalten könnte.

Benutzeravatar der Community
Gemeinschaft

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

Weitere Informationen zu dieser anderen Frage.

  • Sie sind wirklich bibliotheksabhängig (normalerweise die C-Bibliothek, die normalerweise sehr eng mit dem Betriebssystem verknüpft ist). Für den Compiler sind sie nur Funktionen.

    – Donal Fellows

    21. Juni 2010 um 8:19 Uhr

1427900cookie-checkWoher weiß frei, wie viel freizugeben ist?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy