- Dynamischer Speicher
-
Der dynamische Speicher, auch Heap (engl. für ‚Halde‘, ‚Haufen‘), Halden- oder Freispeicher ist ein Speicherbereich, aus dem zur Laufzeit eines Programms zusammenhängende Speicherabschnitte angefordert und in beliebiger Reihenfolge wieder freigegeben werden können. Die Freigabe kann sowohl manuell als auch mit Hilfe einer automatischen Speicherbereinigung erfolgen. Eine Speicheranforderung vom Heap bzw. Freispeicher wird auch dynamische Speicheranforderung genannt. Sie dient den Programmen dazu, über den vom Programmcode und den – fix reservierten – Datenfeldern und dem Stack (Stapelspeicher) belegten Speicher hinaus noch zusätzlichen Pufferspeicher zur Verfügung zu haben.
Inhaltsverzeichnis
Unterschied zum Stack
Der Unterschied zum Stack besteht darin, dass beim Stack angeforderte Speicherabschnitte in der umgekehrten Reihenfolge wieder freigegeben werden müssen, in der sie angefordert wurden. Dies schränkt die Wiederverwendung nicht länger benötigter Stackbereiche ein; ebenso muss eine Funktion ihre Stack-Speicheransprüche vor ihrer Rückkehr zu der aufrufenden Funktion aufgeben. Beim Stack spricht man auch von automatischer Speicheranforderung. Der Zeitaufwand bei einer automatischen Speicheranforderung zur Laufzeit ist in der Regel deutlich geringer als bei der dynamischen Speicheranforderung. Da für den Stack meist nur ein kleiner Speicherbereich reserviert wird, kann bei intensiver Nutzung durch sehr große oder sehr viele Anforderungen ein unerwünschter Programmabbruch wegen Stapelüberlaufs erfolgen.
Unterstützung von dynamischen Speicheranforderungen in Programmiersprachen
Programmiersprachen unterstützen die dynamische Speicheranforderung auf unterschiedliche Weisen. In ISO-C gibt es dafür beispielsweise die Funktionen malloc(), calloc() und realloc(). Mit der Funktion free() wird der Speicher dann wieder freigegeben.
In ISO-C++ gibt es außer den bereits von C übernommenen Funktionen die Möglichkeit, Speicher dynamisch mit Hilfe von new anzufordern bzw. mit delete wieder freizugeben.
Speicherverwaltung
Im Vergleich zum Stack ist die Verwaltung des Heaps durch die Laufzeitumgebung aufwändiger, da je nach System das Anfordern und Freigeben von Speicherabschnitten völlig dynamisch und unvorhersehbar erfolgen kann und zwischen den verwendeten Speicherabschnitten unverwendete Abschnitte sein können. An die dynamische Speicherverwaltung werden die folgenden, einander teilweise widersprechenden Anforderungen gestellt:
- Hohe Geschwindigkeit
- Effiziente Speichernutzung
- Geringer Verwaltungsaufwand
- Flexible und mächtige Bibliotheksroutinen (sofern solche überhaupt vorhanden sind)
Da Programme Speicherbereiche in unterschiedlichen Größen anfordern können, muss auch die Heap-Verwaltung Blöcke unterschiedlicher Größe bereit halten, da es Verschwendung wäre, z. B. einen Block mit 10 KiloByte zu reservieren, wenn das Programm nur 100 Byte benötigt (best-fit Strategie).
Falls Blöcke auch geteilt werden können, kann es aber umgekehrt auch wieder sinnvoll sein, einen Block mit möglichst großem „Rest“ zu teilen (worst-fit Strategie). Die Überlegung ist, dass ein Bereich mit 900 Byte eher noch verwendet werden kann als ein für best-fit typischer Rest von 2 oder 3 Byte.
Ohne automatische Speicherbereinigung kann es durch Fragmentierung des zur Verfügung stehenden, endlich großen Gesamtspeicherbereiches so weit kommen, dass neue Speicheranforderungen nicht mehr erfüllt werden können, obwohl der insgesamt verfügbare freie Speicher noch ohne Weiteres ausreichen würde.
Für die Anwendungsentwicklung bedeutet die dynamische Speicherverwaltung einen erheblichen zusätzlichen Aufwand und bildet eine häufige Fehlerquelle, insbesondere für Speicherlecks. Ein typischer Fehler ist zum Beispiel, dass Referenzen auf dynamisch belegten Speicher unbeabsichtigt überschrieben werden und der ursprünglich referenzierte Bereich nicht mehr freigegeben werden kann. Dies kann dann auch zu sogenannten hängenden Zeigern führen.
Die dynamische Speicherverwaltung bietet dem Anwendungsentwickler die Möglichkeit, die Verwendung des Speichers innerhalb der Anwendung selbst zu steuern. Dies ist insbesondere bei systemnahen Anwendungen, Echtzeitanwendungen oder mobilen Anwendungen von Bedeutung, da hier die nicht-funktionalen Anforderungen gegenüber dem Speicherbedarf beziehungsweise dem Antwortzeitverhalten normaler Anwendungen abweichen können. Durch die stetig wachsende Leistungsfähigkeit der Hardware tritt dieser Aspekt jedoch immer weiter in den Hintergrund.
Weiterführende Artikel
- Speicherüberlauf bei der dynamischen Speicheranforderung, siehe Heap Overflow
Weblinks
Wikimedia Foundation.