C-Array-Instanziierung – Stack- oder Heap-Zuweisung?

Lesezeit: 4 Minuten

Benutzer-Avatar
Shookit

Ich garantiere, dass diese Frage schon einmal gestellt wurde, aber ich konnte sie nicht über die Suche finden; Entschuldigung im Voraus für etwaige Redundanzen.

Es ist mein (möglicherweise falsches) Verständnis, dass Sie nur dann dem Stapel zuweisen, wenn Sie die Größe eines Objekts zur Kompilierzeit kennen. Im Falle der Initialisierung eines Arrays könnten Sie also eine der folgenden Aktionen ausführen (und dies sollte auf den Stapel gehen):

char charArray[50];

Da die Größe dieses Arrays zur Kompilierzeit bekannt ist, sollte dies keine Probleme haben.

Andererseits ist dies (glaube ich) auch ein gültiger Code:

char anotherCharArray[someVariable + 50];

Würde das auch auf den Stack gehen? Ich bin mir ziemlich sicher, dass der Code segfaults ist, wenn Sie dies freigeben (), also denke ich, dass dies der Fall ist, aber es ergibt für mich keinen Sinn. In ähnlicher Weise ist die 100% einzige Situation, in der Sie free() verwenden müssen, wenn die Daten über malloc zugewiesen wurden?

Vielen Dank im Voraus für Ihre Hilfe.

  • @Shookit: Sie müssen angeben, ob Sie über lokale Variablen oder globale Variablen sprechen.

    – PaulR

    13. Oktober 2012 um 15:39 Uhr

  • @PaulR Wenn das Array eine variable Länge hat, kann es sich nicht im globalen Bereich befinden.

    Benutzer529758

    13. Oktober 2012 um 15:46 Uhr

  • Da muss man unterscheiden automatische Speicherung und die Stapel, was eine Low-Level-Methode zum Speichern von Daten ist. Daten, die automatisch gespeichert werden, können auch an anderen Stellen abgelegt werden, beispielsweise in Registern. Im Falle eines lokalen Arrays mit unbekannter Größe (bekannt als VLA:s) kann der Compiler es auf dem Stack platzieren, es ist ihm auch erlaubt, den Speicher auf dem Heap zu allokieren (sofern er ihn an geeigneten Stellen freigibt). Tatsächlich passen VLA:s nicht gut zusammen mit setjmp/longjmp da sie undicht sein könnten (und dies laut C-Norm erlaubt ist).

    – Lindydancer

    13. Oktober 2012 um 17:41 Uhr

Wenn char charArray[50]; im Dateibereich definiert ist (außerhalb aller Funktionen) oder ist static, es wird nicht auf dem Stack sein, es wird eine globale Vorabzuordnung bei der Startvariable des Programms sein. Wenn nicht static und im Funktionsbereich definiert ist, befindet es sich auf dem Stapel.

char anotherCharArray[someVariable + 50]; kann nur im Funktionsbereich definiert werden und befindet sich auf dem Stack.

All das Obige gilt für typische Implementierungen von C. Atypische verwenden möglicherweise den Heap anstelle des Stapels und anstelle des vorab zugewiesenen Speicherplatzes im Datenabschnitt des Programms.

Du nicht free() was nicht belegt ist malloc(), calloc() oder realloc(). Einfach. Einige Funktionen können die Verwendung einer der oben genannten implizieren, z. B. POSIX strdup().

  • Wenn wir im globalen Bereich sind, char someArray[variableLenght]; ist nicht erlaubt…

    Benutzer529758

    13. Oktober 2012 um 15:44 Uhr

  • @H2CO3 Hat die letzte Bearbeitung Mehrdeutigkeiten beseitigt? Ich sehe nicht, wo ich andeuten würde, dass dies im globalen Geltungsbereich zulässig ist.

    – Alexey Frunze

    13. Oktober 2012 um 15:46 Uhr

In ähnlicher Weise ist die 100% einzige Situation, in der Sie free() verwenden müssen, wenn die Daten über malloc zugewiesen wurden?

Ja. (Neben calloc und realloc soll auch deren Rückgabewert sein free()‘d. Ebenso gibt es Funktionen, die malloc() verwenden und diese Tatsache ist beispielsweise dokumentiert strdup() – Der Rückgabewert dieser Funktionen ist ebenfalls mit freizugeben free()offensichtlich.)

char anotherCharArray[someVariable + 50];

Würde das auch auf den Stack gehen?

Ja, das tut es (in den meisten Implementierungen – natürlich nicht stets wahr, dass Sie annehmen, aber auf den meisten Plattformen ist es so). Und ja, das ist ein gültiger Code, aber er ist nur in C99 Standard.

  • In Ordnung, also scheint es, als wäre mein größtes Missverständnis die Annahme, dass die Stack-Speicherzuweisung eine Kenntnis der Größe zur Kompilierzeit erfordert? Ich habe dies als beantwortet markiert (aber du kannst trotzdem gerne auf meinen Kommentar antworten 🙂

    – Shookit

    15. Oktober 2012 um 0:49 Uhr

  • @Shookit Ja, das ist ein völliges Missverständnis; Eine bekannte Größe zu haben, ist irrelevant dafür, wo etwas zugewiesen wird. Der einzige Zusammenhang besteht darin, dass in früheren Versionen von C aus verschiedenen historischen Gründen auto Variablen mussten eine bekannte Größe haben, und zwar nur auto Variablen können auf dem Stapel zugewiesen werden.

    – Jim Balter

    18. Oktober 2012 um 9:54 Uhr

  • @JimBalter hat deine Frage sehr gut beantwortet 🙂

    Benutzer529758

    18. Oktober 2012 um 11:00 Uhr

  • Fantastisch und vielen Dank für die Hilfe aller. Es machte für mich nie Sinn, dass es zur Kompilierzeit bekannt sein musste, da Sie erwarten würden, dass der Stapelrahmen innerhalb des Speicherplatzes so weit wachsen kann, wie er benötigt wird (bis eine andere Funktion aufgerufen wird und ein neuer Stapelrahmen geschaffen).

    – Shookit

    18. Oktober 2012 um 13:49 Uhr

  • Selbst wenn Sie die Größe zur Kompilierzeit kennen, wenn das mehr als ein paar Megabyte und auf dem Stapel sind, verursachen einige C-Implementierungen zur Laufzeit einen Stapelüberlauf. stackoverflow.com/questions/27481707/… (Ha. Zum ersten Mal habe ich den eigenen Namen der Site verwendet.)

    – Camille Goudeseune

    6. Mai 2015 um 16:21 Uhr


1363120cookie-checkC-Array-Instanziierung – Stack- oder Heap-Zuweisung?

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

Privacy policy