Speicher
Last updated
Last updated
Grundlagen von Adressräume und Speichervirtualisierung kennen lernen
Unterschiedliche Adressierung von Programminstruktionen, Heap und Stack verstehen
Das Betriebssystem war vollständig im Hauptspeicher präsent
Ein laufendes Programm (= Prozess) konnte den Rest des Speichers nutzen
Dadurch was alles sehr einfach zu programmieren
Beispiel
Betriebssystem im Speicherbereich 0KB bis 64KB
Das laufende Programm nutzt den gesamten restlichen Speicher ab 64KB
Jeder Prozess hat einen eigenen Speicherinhalt.
Im Beispiel zuvor passt dieser der gesamte Rest des verfügbaren Speichers.
Gibt es mehr Prozesse, muss der Speicher aufgeteilt
werden, d.h. jeder Prozess erhält einen eigenen Speicherbereich, seinen sog. Adressraum (engl. address space).
Auf diesen Adressraum hat nur der Prozess selbst Zugriff, kein anderer Prozess kann auf diesen Adresraum zugreifen
Genügt der Speicher nicht, muss bei jedem Context Switch der Adressraum weggespeichert und später neu geladen werden
Adressräume sind also einfach zu verwendende Abstraktionen des Speichers
Ein Adressraum beinhaltet alle Bestandteile des laufenden Programms
Code
Einfach zu laden, da nicht veränderbar
Stack und Heap
Wachsen und schrumpfen
Durch entgegengesetzte Anordnung ist dies gleichzeitig möglich
Heap wächst "positiv"
Stack wächst "negativ"
Da der Prozess nicht weiß, dass er sich in einem Adressraum befindet, »denkt« er wurde bei Adresse 0 KB in den Speicher geladen
Für jeden Prozess beginnt der Adressraum an Adresse 0 KB
Allerdings liegt der Prozess dabei jedoch wo ganz anders
Hier sprechen wir von einer sog. virtuellen Adresse (engl. virtual address)
Bei jedem Zugriff auf eine Variable, eine Konstante oder bei Laden eines Befehls aus dem Code-Segment muss daher die Adress in die echte physikalische Adresse umgerechnet werden.
Wird implizit (automatisch) reserviert
Compiler reserviert für die Variable x
entsprechend Speicher auf dem Stack
Speicher wird bei Aufruf von func
alloziert und beim Verlassen der Routine wieder freigegeben
Speicher muss explizit durch Entwickler alloziert werden
Hinweis: Compiler reserviert Speicher für Pointer, z.B. int *x
, auf dem Stack
Prozess fordert Speicher auf dem Heap für ein Integer an
Zurück kommt die Speicheradresse, an der der Integer Wert auf dem Heap liegt
Speicher für eine Fließkommazahl reservieren:
Compiler kennt die Größe des Datentyps
Sie auch? 8 Byte, 32-Bit Fließkommazahlen, war schon dran, oder?
Array für 10 Integer-Werte reservieren
Allozierten Speicher wieder freigeben
malloc, free und das Betriebssystem
malloc
und free
beziehen sich immer nur auf den virtuellen Adressraum eines Prozesses
Auch wenn ein Speicherleck gebaut wird und der gesamte Heap voll läuft gilt:
Das Betriebssystem holt sich nach Prozessende den gesamten Speicher zurück
Kann aber Probleme bei langlaufenden Prozessen (Web Server o.ä. machen)
Viel größeres Problem wenn im Betriebssystem selbst ein Speicherleck enthalten ist
malloc
und free
sind selbst keine SysCalls
brk
und sbrk
sind SysCalls zum Ändern des Heaps
mmap
zum Erzeugen eines neuen Speicher-Mappings in den virtuellen Adressraum
Transparenz: Der Prozess weiß nichts von seinem Glück und denkt er greift auf physikalischen Speicher zu
Effizienz: In Bezug auf Speicher- als auch Zeit (z.B. unterstützt durch Hardware-Features)
Sicherheit: Prozess müssen voreinander geschützt sein
Was könnte beim Verwalten von Speicher schon schiefgehen?
Vergessen Speicher zu reservieren
▶ Resultiert in sog. » Segmentation Fault«
Korrekt wäre:
Das kann laufen, kann aber auch abstürzen
Je nachdem ob malloc
hier ggf. ein Byte mehr alloziert
Verlassen sollten Sie sich darauf allerdings nicht… 🙈
Egal ob initialisiert oder nicht, es wird auf jeden Fall etwas aus dem Speicher gelesen
Und zwar das was vorher drin war 😲
Nennt sich dann »Uninitialized Read«
Ein Klassiker
Hatten wir schon einmal zu Beginn der Vorlesungsreihe
Herzlichen Glückwunsch, Sie haben ein Speicherleck (engl. memory leak) gebaut 🤦♂️
Kann man auch bei höheren Programmiersprachen erreichen, indem Referenzen nicht »aufgeräumt« wer
Klingt schon so, als wäre das keine gute Idee
Nennt sich »Dangling Pointer«
GGf. noch benötigte Daten können ab dann durch erneutes malloc
überschreiben werden
Man sollte denken, das sollte kein Unterschied machen
Ergebnis ist allerdings nicht exakt definiert
Nennt sich »Double Free«
Immer wieder gut, um die zugrundeliegenden Bibliotheken zur Speicherverwaltung maximal zu verwirren 😵
Man sollte denken, das sollte kein Unterschied machen
Ergebnis ist allerdings nicht exakt definiert
Nennt sich »Double Free«
Immer wieder gut, um die zugrundeliegenden Bibliotheken zur Speicherverwaltung maximal zu verwirren 😵
Bearbeiten Sie die Programmieraufgabe 1 (Lab 01: Stack)