Der Martin: Stack und Heap

Beitrag lesen

Moin,

Und du bekommst meistens mehr Speicher, als du eigentlich anforderst. Windows teilt beispielsweise Speicher nur in Portionen von 4kB zu; wenn die Anwendung also 24 Bytes anfordert, bekommt sie 4kB. Das ist aber systemabhängig.
Aber doch nur, wenn eine neue Page angefordert wird. In diese legt der Heapmanager dann solange weitere Variablen rein, bis die Page voll ist.

kann es sein, dass du hier die Speicherverwaltung des OS und die der C-Runtime vermischt hast? AFAIK arbeitet die C/C++-Runtime mit malloc() oder dem new-Operator so, wie du beschrieben hast: Sie fordert einen großen Block Speicher vom OS an, und gibt bei jedem malloc()-Aufruf kleine Häppchen davon an das Programm. Divide et impera. ;-)
Die Speicherverwaltung des OS selbst (hier als Beispiel Windows) macht sowas nicht. Wenn ich von Windows einen Speicherblock mit GlobalAlloc() anfordere, dann kann die anfordernde Funktion sicher sein, dass sie das zugeteilte Segment exklusiv hat, und nicht mit anderen teilen muss. Außerdem, wie schon gesagt, bekomme ich Speicher von Windows immer nur in Vielfachen von 4kB.

Das eigentliche Problem unter Windows ist, dass der Heapmanager diesen Speicher für Blöcke kleiner 512k nicht wieder frei gibt, sonder nur decommittet.

Hö?

Allokiert man seinen gesammten eigenen Addrerssraum (2GB unter 32Bit Windows Systemen) mit kleinen Blöcken, gibt diese dann alle wieder frei und versucht dann einen großen Block zu allokieren, geht das schief (unter WinXP SP2 jedenfalls), weil der Heapmanager für kleine Blöcke eine extra Verwaltung hat um die Fragmentierung zu verbessern.

Kann ich nicht mit Sicherheit beurteilen; allerdings erscheint mir das merkwürdig, denn einer der Vorteile der virtuellen Speicherverwaltung (nicht zu verwechseln mit der Swapdatei!) ist doch, dass man über die Descriptortabellen die 4kB-Kacheln mit gleichbleibenden virtuellen Adressen lustig im physikalischen Adressraum hin- und herschieben kann. So kann man Fragmentierung von vornherein vermeiden, bzw. sie ist aus Applikationssicht nicht erkennbar. Sie entsteht erst, wenn man diesem Speichermanager des OS noch eine zweite Schicht der Speicherverwaltung vorschaltet.

Außerdem ist der Stack bei manchen Rechnerplattformen begrenzt. Auf 16bit-Systemen wie DOS oder Windows 3.x und älter kann der Stack maximal 64kB groß werden, bei 32bit-Systemen kann er theoretisch 4GB umfassen, wenn das OS nicht von sich aus eine Bremse reinhaut.
Der Heap doch auch. Mehr als an Adressraum zur Verfügung steht kann man nicht nutzen.

Stimmt. Aber die maximale Größe des Stacks legt der Programmierer vorher fest, und die kann wesentlich kleiner ausfallen, z.B. 1MB. Bei dieser Festlegung muss er natürlich den Bedarf seines Programms ungefähr abschätzen können. So wäre es übertrieben, für ein Programm mit überwiegend linearem Programmablauf und wenig lokalen Daten einen 16MB-Stack zu reservieren; umgekehrt wird man den Stack nicht auf 64kB begrenzen, wenn man ein Programm mit zahlreichen Rekursionen und üppig funktionslokalen Daten hat.

So long,
 Martin

--
Die Zeit, die man zur Fertigstellung eines Projekts wirklich braucht, ist immer mindestens doppelt so lang wie geplant.
Wurde dieser Umstand bei der Planung bereits berücksichtigt, gilt das Prinzip der Rekursion.
Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(