Präsentation herunterladen
Die Präsentation wird geladen. Bitte warten
Veröffentlicht von:Hetty Braun Geändert vor über 8 Jahren
1
C Tutorium – Memory Management – Knut Stolze
2
2 Agenda Einführung in die Speicherverwaltung Stack vs. Heap Malloc Free Sizeof Tipps/Hinweise
3
3 Speicherverwaltung Speicher (RAM) ist (meist) liniar und ein zusammenhängender Bereich – Muss unterteilt/strukturiert werden Alle Informationen (Daten und Programme) müssen im Hauptspeicher abgelegt werden Virtualisierung von Speicher – Erweiterung des physisch vorhandenen Hauptspeichers um Paging/Swap Space – Betriebssystem kümmert sich um Paging/Swapping
4
4 Speicherverwaltung (2) Programme können parallel laufen – Jedes Programm ist unabhängig von anderen – Speicher muss zugeteilt/reserviert werden – Jede Variable in einem Programm muss in einem zuvor reservierten Speicherbereich abgelegt werden! Prozess 1Prozess 3 Gesamter (virtueller) Speicher
5
5 Stack vs. Heap Speicher, der einem Programm insgesamt zur Verfügung steht HeapStack Stack-Pointer
6
6 Stack vs. Heap (2) Stack und Heap teilen sich gesamten zur Verfügung stehenden Speicher – Pro Prozess Heap: dynamisch benötigter Speicher Stack: statisch verwendeter Speicher
7
7 Stack Für alle statischen Informationen während des Programmablaufs – Wird zur Laufzeit allokiert – nicht beim Starten! Aufrufinformationen – Welche Funktion wurde von wo aufgerufen – Parameter der aufgerufenen Funktion – Rücksprungadresse Statische Variablen in der Funktion – Z.B. int a[50] Genügend Speicher für 50 “int” Werte – Werden automatisch beim Verlassen der Funktion aufgeräumt, d.h. der Speicher wird wieder freigegeben
8
8 Stack (2) Andere Programmiersprachen – C++: Destruktor von Objekten wird aufgerufen und Speicher wird freigegeben – Java: Reference count von Objekten auf dem Stack wird reduziert garbage collector räumt auf Allokation auf dem Stack ist schneller/performanter als vom Heap – Heap kann Fragmentieren; Stack nicht
9
9 Heap Für dynamisch allokierten Speicher Wird vom Betriebssystem (OS) verwaltet – Funktion “malloc” fordert Speicherblock an Passender Block muss gesucht, reserviert und zurückgegeben werden – Funktion “free” gibt zuvor angeforderten Speicherblock wieder frei OS verwaltet alle angeforderten Speicherblöcke Speicher des Heaps kann fragmentieren
10
10 Ulimit (Unix) Legt Maximum von Resourcen für einen Prozess fest: – Maximal nutzbarer Speicherbereich (virtuell) – Größe des Stacks – Größe von “core” Dateien – Größe des “data segment” eines Prozesses – Größe von Dateien, die ein Prozess anlegen kann – Größe des ge”pin”ten SpeicherbereichsAnzahl der geöffneten Dateien – Blockgröße bei Pipes – Anzahl der Prozesse eines Nutzers – CPU-Zeit
11
11 Malloc Fordere einen Speicherblock vom Heap an ptr = malloc(size); – “ptr” ist ein Zeiger auf den Beginn des Speicherblocks Ein Zeiger ist eine Adresse im Hauptspeicher – “size” ist die Größe des Blocks in Anzahl von Bytes Speicherblock Heap im Hauptspeicher ptr (0x01234567)
12
12 Malloc (2) Gibt Zeiger vom Typ “void *” zurück – Typ der Werte, die im Speicherblock hinterlegt werden sollen ist “malloc” nicht bekannt – Typ muss mittels Cast umgewandelt werden int *ptr = NULL; ptr = (int *)malloc(size); Es darf nicht ausserhalb des allokierten Speicherblocks zugegriffen werden – Speicher könnte anderen Prozessen oder anderen Datenstrukturen des gleichen Prozesses gehören
13
13 Malloc (3) Ähnliche Systemfunktionen: – calloc Andere Programmiersprachen verwenden ähnliche Operatoren, die Typisierung gleich mitliefern, d.h. der Cast wird intern gleich mit erledigt: – C++: Class *object = new Class(); – Java: Class object = new Class();
14
14 Grundlagen von Zeiger-Arithmetik Ergebnis von “malloc” zeigt auf 1 Element des spezifizierten Datentyps ptr = (int *)malloc(size); – “ptr” zeigt auf ein “int”-Wert Zeigerarithmetik arbeitet grundsätzlich auf dem zu Grunde liegenden Datentyp – “ptr = ptr + 1;” lässt den Zeiger auf den nächsten “int”- Wert zeigen (und nicht auf das zweite Byte)
15
15 Free Angeforderte Speicherblöcke müssen wieder freigegeben werden free(ptr); – Sobald nicht mehr gebraucht – Geschieht automatisch beim Programmende Zeiger auf Speicherblock darf bis zum “free” nicht verloren gehen! Ein Block kann nur genau 1x freigegeben werden – Mehrfache “free” Operationen könnten einen falschen Block freigeben – Danach darf Block nicht mehr verwendet werden
16
16 Free (2) Freigegebener Block (oder ein Teil davon) kann beim nächsten “malloc” wieder vergeben werden Andere Programmiersprachen verwenden intern auch “free”: – C++: delete-Operator – Java: garbage collection
17
17 Sizeof Operator Anzahl der Bytes von Datentypen kann von Plattform zu Plattform variieren – Z.B. unterschiedliche Größen von “int” Werten (32 vs. 64 Bit Prozessoren) – Unterschiedliche Optimierungsstrategien der Compiler – Unterschiedliche Mächtigkeit/Performance der Adressierungsbefehle des Prozessors – Zugriff auf Speicheradressen, die ein Vielfaches von 4 Bytes sind, oft schneller als Adressierung einzelner Bytes
18
18 Sizeof Operator (2) Padding-Bytes können vom Compiler eingeschoben werden Genaue Größe von Strukturen oft nicht bekannt oder soll nicht hart-verdrahtet werden (Portabilität)
19
19 Sizeof Operator (3) “sizeof” berechnet Größe eines Wertes oder eines Datentyps size = sizeof(int); size = sizeof(struct myStruct); size = sizeof myValue; – Anzahl an Bytes, die die physisch Repräsentation im Speicher benötigt ptr = (int *)malloc(N * sizeof(int)); Kann bereits zur Übersetzungszeit errechnet werden und belastet somit nicht die Laufzeit
20
20 Realloc Vorgrößern von Speicherblöcken ist nicht direkt möglich – Andere Speicherblöcke können physisch im Speicher direkt dahinter liegen int *ptr = NULL; int *biggerPtr = NULL; ptr = (int *)malloc(orig_size); … biggerPtr = (int *)realloc(ptr, new_size);
21
21 Memset, memcpy, memmove Angeforderte Speicherblöcke (malloc) sollten immer initialisiert werden memset(ptr, 0x00, size); – Bei sicherheitskritischen Anwendung ist ein “Leeren” vor dem Freigeben auch oft ratsam! Kopieren zwischen überlappungsfreien Speicherblöcken memcpy(destination, source, size); Kopieren zwischen überlappenden Speicherblöcken memmove(destination, source, size);
22
22 Richtlinien & Tipps Speicherallokation kann fehl schlagen!! – Ergebnis ist dann NULL-Zeiger – Ergebnis muss immer überprüft werden Speicherblock nach “free” nicht weiter verwenden – Am besten Zeiger auf NULL setzen: free(ptr); ptr = NULL
23
23 Richtlinien & Tipps (2) Alle Variablen sofort bei der Deklaration initialisieren char *str = NULL; int counter = 0; str = (char *)malloc(strlen(orig_str)+1); if (!str) { … } memset(str, 0x00, strlen(orig_str)+1);
24
24 Potientielle Probleme Keine gute Kontrolle über Speicher – Keine Gruppierung von Speicher – Keine Fehlermeldung beim falschen Freigeben Programm stürzt eventuell ab; vielleicht auch an ganz anderer Stelle Buffer Overflow verhindern – Zugriff ausserhalb des aktuellen Speicherblocks – Oft keine/unzureichende Prüfung von Überläufen – Kann sich oft zu Sicherheitsproblemen ausweiten
25
25 Potentielle Probleme (2) Memory Leaks – angeforderter Speicher wird nie freigegeben – Zeiger auf Speicherblock ist verloren gegangen Funktionen dürfen keinen Zeiger in den Stack zurückgeben – Informationen auf dem Stack sind beim Verlassen der Funktion nicht mehr gültig “free” auf Objekt auf dem Stack ist nicht zulässig – Führt meist zum Absturz des Programms
Ähnliche Präsentationen
© 2024 SlidePlayer.org Inc.
All rights reserved.