Unterschied Stack <--> Heap



  • Moin,

    kann mir jemand in ein paar Worten erklären, worin die Unterschiede zwischen Stack- und Heap-Variablen liegen und wann man welche Form bevorzugen sollte?

    Außerdem:

    Sind folgende zwei Zeilen was den Speicher betrifft identisch oder handelt es sich einmal um Heap- und einmal um Stack-Speicherallokation?

    char * p = new char[150];
    char p[150];
    

    //EDIT: Unterschiede, die im Laufe des Threads genannt wurden:

    Stack:
    + Effizienter (was Performance angeht)
    + Automatische Speicherverwaltung
    - Speichergröße muss schon zur Compile-Zeit feststehen

    Heap:
    + Mehr Speicherplatz
    + Laufzeitspeicher / dynamischer Speicher (man kann selber Geburt und Tod der Objekte bestimmen; Größe kann zur Laufzeit angegeben werden)
    - Manuelle Speicherverwaltung nötig (new/delete!)



  • Der Unterschied zwischen Speicher auf dem Stack und Speicher auf dem Heap ist der, dass auf dem Stack angelegte Variablen, also sowas wie dein

    char p[150];
    

    beim Verlassen des Blocks (oder der Funktion) in dem/der sie deklariert wurden wieder zerstört werden.

    Variablen auf dem Heap, also sowas wie dein

    char *p = new char[150];
    

    bleiben solange bestehen, bis man sie mit delete (in deinem Fall zum Beispiel)

    delete[] p;
    

    wieder explizit freigibt (oder bis zum Ende des Programms).

    Dadurch entscheidet man auch, wann man welche Form braucht. Im Normalfall wird man Variablen auf dem Stack anlegen, aber wenn man zum Beispiel verkettete Listen anlegen will, dann ist das mit Stackvariablen unmöglich. Genauso ist es in C++ auch mit Arrays, die eine Länge haben, die erst zur Laufzeit feststeht, also sowas wie

    int length = 0;
    cin >> length;
    char *p = new char[length];
    //kram
    delete[] p;
    

    Wenn du das mit einem einfachen

    char p[length];
    

    versuchst, dürfte das auf einem standardkonformen Compiler nicht funktionieren.

    Ich hoffe, das hat dir ein bisschen geholfen...

    Felix

    EDIT: Und normalerweise ist der HEap viel größer als der Stack, wenn man also sehr große Objekte oder Arrays hat, wird man die auch lieber auf dem Heap als auf dem Stack anlegen.



  • TheBrain schrieb:

    ... und wann man welche Form bevorzugen sollte?

    Wenns geht Stack. Irgendwas auch den Heap zu tun, was nicht muss, ist nur unnötiger Aufwand.



  • Ok, danke euch beiden. Ich fasse also zusammen:

    Stack-Vorteile:
    - Effizienter

    Heap-Vorteile:
    - Mehr Speicherplatz (normalerweise)
    - Laufzeitspeicher



  • Kleine, nicht unwichtige Ergänzung: 😉

    Stack-Vorteile:
    - Effizienter (was Performance angeht)
    - Man muss sich nicht selber um die Speicherverwaltung kümmern

    Heap-Vorteile:
    - Mehr Speicherplatz (normalerweise)
    - Laufzeitspeicher (man kann selber Geburt und Tod der Objekte bestimmen)



  • Der Ausgleich zum 2:2 😉

    Ich halte das auch mal im ersten Beitrag fest, vll. fällt ja noch jemandem was ein.



  • man kann auch dynamische objekte auf den stack legen. siehe zB alloca()



  • Stack == Stapel
    Heap == haufne


  • Administrator

    Shade Of Mine schrieb:

    man kann auch dynamische objekte auf den stack legen. siehe zB alloca()

    Aber alloca ist nicht standardisiert und es wird nicht empfohlen es zu benutzen. Siehe z.B. hier:
    http://c-faq.com/malloc/alloca.html

    Würde ich daher in so einem Thread eher nicht nennen 🙂

    Grüssli



  • Dravere schrieb:

    Würde ich daher in so einem Thread eher nicht nennen 🙂

    alloca wurde quasi in den neuen C Standard aufgenommen - in der Form von VLA (variable length arrays).

    es kann von fall zu fall also schon sinn machen alloca - oder etwas gleichbedeutendes zu verwenden. und deshalb macht es auch sinn das hier zu erwaehnen...


  • Administrator

    Shade Of Mine schrieb:

    alloca wurde quasi in den neuen C Standard aufgenommen - in der Form von VLA (variable length arrays).

    es kann von fall zu fall also schon sinn machen alloca - oder etwas gleichbedeutendes zu verwenden. und deshalb macht es auch sinn das hier zu erwaehnen...

    Neuen C Standard? Also nicht C98? Also nicht im C++ Standard vorhanden? Also doch nicht sinnvoll? Also zumindest wegen der Erwähnung in diesem Thread. 🙂

    Grüssli



  • Um das auch mal zu erwähnen. C++ kennt keinen Stack, oder Heap. Er kennt nur Objekte, welche automatisch (auto) verwaltet werden und solche, die der Benutzer verwalten muss. Wie das geschieht ist schlussendlich eine Frage der jeweiligen Implementierung. Und somit ist auch der Geschwindigkeitsaspekt Implementierungsspezifisch.



  • Dravere schrieb:

    Neuen C Standard? Also nicht C98? Also nicht im C++ Standard vorhanden? Also doch nicht sinnvoll? Also zumindest wegen der Erwähnung in diesem Thread. 🙂

    wenn wir nur von reinen c++ standard ausgehen, dann ist der thread sowieso komplett offtopic da c++ stack und heap nicht kennt und nicht trennt.

    wenn jemand aber wissen will was der stack ist, dann sollte er auch erfahren dass man sehr wohl dynamisch auf dem stack speicher allokieren kann.


  • Administrator

    So hab mich nochmals informiert. Wenn ich das richtig verstanden habe, dann ist alloca nicht im C99 Standard drin, sondern es wurden die VLA implementiert, welche deutlich einfach funktionieren. Visual C++ und der GNU C Compiler unterstützen aber beide noch keine VLAs. Daher frage ich mich echt, wie sinnvoll die Erwähnung ist. Dann würde ich eher darauf hinweisen, dass laut C99 Standard, man das folgende schreiben kann:

    void foo(int length)
    {
      float vars[length];
    
      // Verwenden von vars.
    } // vars wird autoamtisch freigegeben.
    

    Quasi eine Art von automatischem scope_ptr, nur dass der Speicher unter Umständen deutlich schneller allokiert und wieder freigegeben werden kann.

    Weisst du ob dies auch im neuen C++ Standard enthalten sein wird? Ist eigentlich ein echt geniales Feature.

    Grüssli



  • Dravere schrieb:

    Ist eigentlich ein echt geniales Feature.

    Da der C++ Standard keinen Stack kennt, wird es wohl nicht standardisiert werden. Aber jede Plattform die ich kenne bietet ein alloca ein.



  • Dravere schrieb:

    void foo(int length)
    {
      float vars[length];
    
      // Verwenden von vars.
    } // vars wird autoamtisch freigegeben.
    

    So was geht bisher nicht? Muss man dafür new und delete verwenden?



  • Dravere schrieb:

    Visual C++ und der GNU C Compiler unterstützen aber beide noch keine VLAs.

    Die gcc kann VLAs schon länger (vor C99 iirc auch schon), also auch im C++-Modus als Erweiterung. Es gibt allerdings kleine Unterschiede in der Definition von VLA in C99 und in der gcc, so dass das noch als "broken" gewertet wird. Welches Unterschiede das sind habe ich ehrlich gesagt nie richtig verstanden, aber ich bezweifle, dass das sooo dramatisch ist. Wenn man das Ding als C++-Erweiterung benutzt ist das ohnehin wurscht.

    Dravere schrieb:

    Weisst du ob dies auch im neuen C++ Standard enthalten sein wird? Ist eigentlich ein echt geniales Feature.

    Ich bin was C++0x angeht zwar ziemlich planlos, aber ich meine gehört zu haben, dass es nicht kommen soll.

    Shade Of Mine schrieb:

    Dravere schrieb:

    Ist eigentlich ein echt geniales Feature.

    Da der C++ Standard keinen Stack kennt, wird es wohl nicht standardisiert werden. Aber jede Plattform die ich kenne bietet ein alloca ein.

    Ermm, der C-Standard kennt auch keinen Stack. Hat niemand daran gehindert das entsprechend zu verpacken (z.B.: "Array objects declared with the static or extern storage-class specifier cannot have a variable length array (VLA) type!")



  • TheBrain schrieb:

    So was geht bisher nicht? Muss man dafür new und delete verwenden?

    Ja. Kommt auf den Compiler an. Manche bieten es afaik an.
    Sprich: Es ist nicht standardisiert, dass es geht. Muss also nicht gehen.


Anmelden zum Antworten