Wo "ist" der Heap
-
.
^du, hustbaer... erst lesen, dann denken, dann schreiben.
gell, hustbaer? :)^
-
drakon schrieb:
Wenn ich mich jetzt nicht ganz irre, habe ich im Stroustrup sogar gelesen, dass es keinen Unterschied des "Stacks" und des "Heaps" mehr gibt, ausser, dass alles, was als "Stack" bezeichnet wird einfach automatisch wieder freigegeben wird und das auf dem "Heap" nicht. Dafür gäbe es ja noch:
autoWas aber überflüssig ist.
Also so wie du das formulierst gibt das imo kein Sinn. Klar, dass aus Sicht des Betriebsystems auch der Stack eines Prozesses auf dem "Freispeicher"/Heap liegt. Aber wenn dein Prozess mal schnell ein paar Werte auf das Stacksegment pusht, geht das 1. ganz anderst als bei einer Freispeicherallokation und 2. logischerweise auch viel schneller, denn das kann der Prozessor "von sich aus", während du bei einer Allokation auf dem Heap allein durch das Verlassen des Protectedmode länger brauchst.
(bezieht sich logischerweise nun nur auf entsprechende Architekturen, aber das hat er eh schon eingegrenz, indem er von Windows sprach)
-
@Entenwickler: ich denke er meinte einfach dass auch Sicht von C++ kein grundlegender Unterschied besteht.
Wie das dann implementiert ist ist letztlich egal.
Theoretisch könnte eine Implementierung den Speicher für "automatic storage" Objekte genauso vom OS anfordern - MUSS ja nicht der Stack verwendet werden dafür. Muss nur automatisch wieder freigegeben werden.p.S.: genausowenig muss man in Ring 0 wechseln (was das mit protected mode verlassen zu tun hat weiss ich im übrigen auch nicht, das wäre wieder was anderes, und hier sowieso nicht nötig), wenn man Speicher in ausreichend grossen Stücken vom OS holt muss man das OS nur ganz selten bemühen. Im Extremfall nur 1x bei Programmstart (z.B. 1GB vom OS holen und fertig, mehr gibts dann halt nicht).
-
Klar man kann sich gleich ein großen Block ausleihen, und dann den selber verwalten.
Und ansonsten: Klar, im Standard ist nicht vorgeschrieben wie spezielle Dinge implementiert werden müssen, aber das liegt einfach daran, dass es so viele Architekturen gibt für die man das nicht verallgemeinter kann. Aber auf einem x86 sollte wohl der Unterschied Stack<>Heap (aka automatic storage <> free store) ganz klar sein.
Und wenn der Threadautor davon redet, dass "sein Arbeitsspeicher sich nicht verändert" wird wohl bereits ein OS wie Linux/Windows oder whatever haben, bei dem das zutrifft.
PS: Hab grad protected mode mit den blöden Ringen verwechselt, bin wohl bissl durcheinander Oo
-
Aua, die Aussage dass es nur wenige Unterschiede zwischen Heap und Stack gibt ist falsch. Denn:
- Heap und Stack sind im Endeffekt nichts anderes als abstrakte Datentypen (Queue, Baum). Sie sind Speicher/Container welche Elemente aufnehmen und löschen können.
Ein Stack ist ein Stabel. Wenn man ein Element hinzufügt wird dies ("bildlich gesprochen) auf das letzte Element draufgelegt. Ein Heap ist dagegen eine Halde. Fügt man ein Element einem Heap hinzu wird dies unterhalb des letzten Elementes hinzugefügt.Summa sumarum, ein Heap wächst von oben nach unten (bezogen auf die Adresse des nächsten freien Elements) während ein Stack von unten nach oben wächst.
Damit lässt sich auch die initale Frage beantworten. Wenn man einem Prozess einen festen Arbeitsraum im RAM zuordnet, so werden Objekte auf dem Heap im dem Bereich mit hoher Adresse abgelegt. Objekte auf dem Stack dagegen im Bereich mit niedrigen Adressen abgebildet.
-
Ja, technisch gesehen schon.
Aber aus C++ aus gesehen muss es ja nicht unbedingt auf dem Stack sein.
Wenn man also normal eine Variabel anlegt, so heisst das nicht, dass es auf
dem Stack geschehen muss, sondern einfach nur, dass er automatisch behandelt wird.
Im Gegenzug heisst es, wenn man Speicher mit new bezieht lediglich, dass dieser einen dynamische behandelt wird.
Wo das geschieht ist Sache der Implementation.
-
Das auf x86 übliche (vereinfachte) Speichermodell sieht so aus:
(0) Code | Heap -> | <- Stack (max)
Der Code-Bereich enthält die Maschinenbefehle des Programms und ist vom BS schreibgeschützt. Ein Schreibzugriff führt zu einem Segmentation Fault.
Der Heap befindet sich oberhalb des Code-Bereichs. Er wächst in Richtung aufsteigender Speicheradressen. Der Speicher wird von dem Programm dynamisch, d.h. zu beliebigen Zeitpunkten allokiert und freigegeben.
Der Stack befindet sich am oberen Ende des Speichers. Er wächst in Richtung absteigender Adressen. Ein Stack wird deshalb auch Kellerspeicher genannt (für jedes neue Element muss man den Keller weiter hinabsteigen). Jeder (Unter-)Funktionsaufruf fügt einen Stackrahmen hinzu, der Platz für lokale Variablen, die Funktionsparameter und die Rücksprungadresse der Funktion enthält. Diese Rahmen werden automatisch wieder entfernt, wenn die Funktion zurückkehrt (return oder throw).Das ist jetzt sehr vereinfacht (ohne Bibliotheken, statische Konstanten, Programmparameter, etc). Details in der Literatur.
Zur Thread-Frage: Schon mal auf Fehlschlag überprüft? new liefert entweder 0 zurück oder wirft eine Ausnahme, wenn kein Speicher allokiert werden kann.
-
deha schrieb:
Zur Thread-Frage: Schon mal auf Fehlschlag überprüft? new liefert entweder 0 zurück oder wirft eine Ausnahme, wenn kein Speicher allokiert werden kann.
Und das konkrete Verhalten sucht es sich je nach Situation aus?

In ISO C++ wirft new eine Exception, wenn kein Speicher allokiert werden kann.
-
camper schrieb:
queer_boy schrieb:
betriebssystemmagie. wozu sollte der speicher denn tatsächlich im arbeitsspeicher reserviert werden, wenn du ihn nicht verwendest?
sobald du darauf zugreifen willst, wird er dir auch in den RAM gemappt werden.Nicht bei new (oder irgendeine andere Allokationsfunktion der Standardbibliothek). Andernfalls könnte dem Programm jederzeit der Speicher ausgehen, wenn zum ersten Mal auf bereits erfolgreich allokierten Speicher zugegriffen wird.
das passiert aber, ohne dass das programm es bemerkt. das OS friert notfalls andere prozesse ein, damit dein prozess den speicher bekommt und wenn man wenig davon hat, läuft eben alles extrem langsam.

-
LordJaxom schrieb:
deha schrieb:
Zur Thread-Frage: Schon mal auf Fehlschlag überprüft? new liefert entweder 0 zurück oder wirft eine Ausnahme, wenn kein Speicher allokiert werden kann.
Und das konkrete Verhalten sucht es sich je nach Situation aus?

In ISO C++ wirft new eine Exception, wenn kein Speicher allokiert werden kann.
Oder gibt 0 zurück wenn du std::nothrow verwendest.
Da hatte deha schon recht
-
evilissimo schrieb:
LordJaxom schrieb:
In ISO C++ wirft new eine Exception, wenn kein Speicher allokiert werden kann.
Oder gibt 0 zurück wenn du std::nothrow verwendest.
Da hatte deha schon recht
Das stimmt schon, wenn man denn vom nothrow-new redet. Ich denke die Benutzung von nothrow-new ist ungewöhnlich genug dass man das nicht zum Standardfall machen sollte. New in C++ (so wie es allgemein angewendet wird und in diesem Thread ausschließlich angewendet wurde) wirft eine Exception.
Sonst hätte man die Aussage ergänzen müssen um "...oder schlägt niemals fehl" (placement-new ist auch ein new ;)).