Early first draft Höllische Programmiersprachen Seminar im WS 2014/15 Speichermanagement

Ähnliche Dokumente
Vorlesung Programmieren

Dynamische Speicherverwaltung

Speicherverwaltung in C

Universität Hamburg. Seminar: Effiziente Programmierung in C. Referenzzählung. Autoren: Kevin Köster. Betreuer: Michael Kuhn

Software Entwicklung 1

Speichermanagement Software Entwicklung 1

Informatik II SS Inhalt. Objektlebensdauer (2/3) Objektlebensdauer (1/3)

Speichermanagement Software Entwicklung 1

Dynamisches Speichermanagement

Programmieren in Java

Informatik. Pointer (Dynamisch) Vorlesung. 17. Dezember 2018 SoSe 2018 FB Ing - SB Umwelttechnik und Dienstleistung - Informatik Thomas Hoch 1

Programmiertechnik II

Agenda. Informatik I WS05/06 Folien von Tobias Dezulian

Einführung in die Programmierung

Programmieren I. Kapitel 12. Referenzen

Übersicht. Speichertypen. Speicherverwaltung und -nutzung. Programmieren in C

6 Speicherorganisation

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Dynamische Speicherverwaltung

Einführung in die Programmierung zusammengesetzte Datentypen, dynamischer Speicher

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Crashkurs C++ - Teil 1

6 Speicherorganisation

Algorithmen und Datenstrukturen

C++ - Einführung in die Programmiersprache Zeiger, Referenzen und Strukturen. Leibniz Universität IT Services Anja Aue

Praxisorientierte Einführung in C++ Lektion: "Dynamische Speicherverwaltung"

Zeiger und dynamischer Speicher

Concurrent Garbage Collector

Valgrind. Speicherleaks und Bugs finden. Frederik Heber. Seminarreihe Technische Numerik. Institut für Numerische Simulation, Universität Bonn

Lokale Strategien zur Garbage Collection Problemstellung der verteilten Gargabe Collection Algorithmen

Programmierkurs. Steffen Müthing. January 18, Interdisciplinary Center for Scientific Computing, Heidelberg University

Was ist Reference Counting Implementierung. Ende. Reference Counting. Kevin Köster. Uni Hamburg. 31. März Kevin Köster Reference Counting 1/58

Informatik - Übungsstunde

C++ Teil 5. Sven Groß. 13. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 18

Der Gnu-C++-Compiler allerdings lässt den oben beschriebenen Code durchgehen. Das ist allerdings nicht Standardkonform und sollte deswegen vermieden

Dynamischer Speicher

9 Zeiger (Pointer). Dynamischer Speicher

6. Verkettete Strukturen: Listen

Programmieren in C. Rekursive Strukturen. Prof. Dr. Nikolaus Wulff

Garbage Collection. Maik Theisen Betreuer: Guido Tack

Einführung in die Programmiersprache C

Einführung in die Programmiersprache C

Betriebssysteme. Tafelübung 4. Speicherverwaltung. Olaf Spinczyk.

Betriebssysteme. Agenda. Tafelübung 4. Speicherverwaltung. Olaf Spinczyk.

Grundlagen der Informatik 11. Zeiger

Dynamische Speicherverwaltung

1 pulsierender Speicher

7. Organisation von Informationen

Debugging und Speicherfehler. Seminar Effiziente Programmierung Kadir Duman

Programmierung für mobile Endgeräte

Dynamische Speicherverwaltung

Eindimensionale Arrays und Heap

Programmierwerkstatt. Arrays, Pointer und Referenzen

Übungspaket 29 Dynamische Speicherverwaltung: malloc() und free()

C++ Teil 6. Sven Groß. 23. Nov Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 15

Berühmte Informatiker

Objektorientierte Programmierung II

Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften

Einstieg in die Informatik mit Java

Programmierung mit C Zeiger

7 Laufzeit-Speicherverwaltung

Übungen zu Systemprogrammierung 1

Übungen zu Systemprogrammierung 1 (SP1)

Automatisches Speichermanagement

Garbage Collection. Alexander van Renen

Eine einfache Speicherverwaltung 211

Freispeicherverwaltung

Informatik II Übung 05. Benjamin Hepp 3 April 2017

Speicherverwaltung. Objektorientierte Programmierung. (Winter 2006/2007) Lebensdauer von Objekten. new, delete. Beispiel: Verkettete Listen

Übungen zu Softwaresysteme I Jürgen Kleinöder Universität Erlangen-Nürnberg Informatik 4, 2004 E-Uebung3.fm

Schwerpunkte. Verkettete Listen. Verkettete Listen: 7. Verkettete Strukturen: Listen. Überblick und Grundprinzip. Vergleich: Arrays verkettete Listen

7. Verkettete Strukturen: Listen

Betriebssysteme. Tafelübung 4. Speicherverwaltung. Olaf Spinczyk.

C++ Teil 6. Sven Groß. 27. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 14

Literatur. [4-1] Denert, Ernst; Franck, Reinhold: Datenstrukturen. BI Wissenschaftsverlag, 1977

Zeiger in C und C++ Zeiger in Java und C/C++

Freispeicherverwaltung Martin Wahl,

C++ Teil 7. Sven Groß. 30. Nov Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 13

Programmieren in C. Speicher anfordern, Unions und Bitfelder. Prof. Dr. Nikolaus Wulff

Teil 8: Dynamische Speicherverwaltung. Prof. Dr. Herbert Fischer Fachhochschule Deggendorf Prof. Dr. Manfred Beham Fachhochschule Amberg-Weiden

2. Programmierung in C

INE1 Speicherverwaltung und zweidimensionale Arrays. Speicherorganisation Dynamischer Speicher in C Zweidimensionale Arrays

Inhalt. 4.5 Arbeit mit Zeigern (engl. Pointer)

Java Garbage Collection

Speicherverwaltung (Swapping und Paging)

2.8 Klassen. Nichtgleichartige Elemente können in Klassen zu einem neuen Typ zusammengefasst werden. Beispiel: Die drei Komponenten

Maschinencode Dateiformat und Stackframes

Objektorientierte Programmierung und Klassen

ALP II Dynamische Datenmengen Datenabstraktion (Teil 2)

Algorithmen und Datenstrukturen

DieÜbersetzung funktionaler Programmiersprachen

Advanced Programming in C

Java Garbage Collector: Funktionsweise und Optimierung. Mathias Dolag Prof. Dr. Peter Mandl (DOAG 2012, )

INE1 Arrays, Zeiger, Datenstrukturen

Tafelübung zu BS 4. Speicherverwaltung

Computergestütztes wissenschaftliches Rechnen SoSe 2004

Seminar Effiziente Programmierung Debugging und Speicherfehler

Variablen. Deklaration: «Datentyp» «Variablenname» Datentyp bestimmt Größe in Bytes: sizeof Beispiel: long int v; Größe: 4 Bytes

Transkript:

Early first draft Höllische Programmiersprachen Seminar im WS 2014/15 Speichermanagement Max Haslbeck Technische Universität München 20.01.2015 Zusammenfassung 1 Einleitung 2 Begriffsklärung Heutzutage erlauben fast alle modernen Programmiersprachen Bereiche des Speichers (Details der Hardwareimplementierung des Speichers sind im Rahmen dieser Arbeit uninteressant) dynamisch anzufordern, d.h. Speicherbereiche zu belegen deren Größe zur Kompilierzeit noch nicht bekannt ist und die auch länger existieren können als die Funktion (oder Subroutine, Methode, ) die sie erstellt hat. Diese Objekte werden auf dem Heap abgelegt, im Gegensatz zum Stack der jeweiligen Funktion. Dynamisch Speicher zu belegen ermöglicht Programmierern verschiedene Dinge wie Objekte verschiedener Größe zu erstellen oder rekursive Datenstrukturen wie Listen oder Bäume zu benutzen. Auf Objekte im Heap kann durch Referenzen, oder auch Pointer genannt, zugegriffen werden. Wie diese genau aussehen hängt von der jeweiligen Implementierung ab. Oft handelt es sich um nichts anderes als die Adressen der jeweiligen Speicherblöcke. 3 Manuelles Speichermanagement C/C++ sind praktisch die einzigen Programmiersprachen, die noch direktes manuelles Speichermanagement erlauben. Die Befehle malloc() und free () werden zum reservieren und zum freigeben von Speicherblöcken verwendet. malloc() nimmt als Argument die Größe des benötigten Speicherplatzes, versucht diesen 1

zu reservieren und gibt dann einen Pointer auf diesen Speicherplatz zurück. Falls dies nicht funktioniert, da z.b. der Heap voll ist, wird ein NULL-Pointer oder eine speziell reservierte Adresse zurückgegeben, je nach Implementierung [1]. Die einfachste Methode Speichermanagement zu betreiben ist natürlich gar kein Speichermanagement zu betreiben. Da das Betriebssystem den von einem Programm angeforderten Speicher nach dessen Beendigung komplett wieder freigibt, ist das durchaus eine Möglichkeit für Programme die nur kurz laufen. Dies kann auch funktionieren, wenn man sich der genauen Speicheranforderungen des Programms bewusst ist und diese definitiv den Heap nicht komplett aufbrauchen. 2 Dies ist natürlich keine Option für Programme mit hohen Speicheranforderungen oder mit hohen Laufzeiten wie z.b. UNIX-daemons ist. Hier liegt es in der Hand des Programmierers nicht mehr benötigten Speicher wieder freizugeben und Referenzen auf undefinierte Speicherbereiche zu vermeiden. Die Komplexität dieses Problems geht natürlich Hand in Hand mit der Komplexität eines Programms. Es gibt mittlerweile auch viele Tools die Programmieren helfen Fehler, wie die unten genannten, zu vermeiden, z.b. valgrind. 3.1 Memory leaks Memory leaks oder zu deutsch Speicherlecks sind einer der bekanntesten Fehler, die bei manueller Speicherverwaltung auftreten können. Hier ein Beispiel in C: #i n c l u d e <s t d l i b. c> void l e a k ( ) 4 { 6 i n t a = malloc ( s i z e o f ( i n t ) ) ; // S p e i c h e r p l a t z wird // r e s e r v i e r t 8 // Von a b e l e g t e r S p e i c h e r wird n i c h t f r e i g e g e b e n 10 } 12 i n t main ( ) { 14 l e a k ( ) 16 // dann z.b. w i e d e r h o l t e s Aufrufen von l e a k ( ) } Bei jedem Aufruf von leak() wird Speicherplatz reserviert, aber nicht mehr freigegeben. Außerhalb der Funktion leak() gibt es auch keine Möglichkeit mehr diesen 2

2 Speicherplatz zu referenzieren. Es kommt zum sogenannten memory leak. Wiederholtes Aufrufen von leak() (z.b. in einer Dauerschleife) führt zu zunehmenden Verschwendung von Speicherplatz auf dem Heap. Was dann normalerweise zur Beendigung des Programms durch das Betriebssystem führt, wenn kein Platz mehr auf dem Heap vorhanden ist. 3.2 Dangling pointers Bei dangling pointers handelt es sich um Referenzen auf Speicherbereiche, die nicht den erwarteteten Wert enthalten. Das kann passieren, wenn Speicherbereiche nicht installiert wurden oder freigegeben wurden und auf sie zugegriffen wird. Ein Beispiel in C: #i n c l u d e <s t d l i b. c> void dang ( i n t p o i n t e r ) 4 { 6 i n t a = p o i n t e r ; 8 f r e e a ; } 10 i n t main ( ) 12 { i n t p = malloc ( s i z e o f ( i n t ) ) ; 14 dang ( p ) ; 16 // Z u g r i f f auf den von p r e f e r e n z i e r t e n S p e i c h e r b e r e i c h // f u e h r t j e t z t zu u n d e f i n i e r t e m Verhalten 18 } 4 Automatisches Speichermanagement Um den Speicher automatisch zu verwalten gibt es mehrere Methoden und vieles hat sich getan seit John McCarthy in LISP zum ersten Mal einen garbage collector zur Speicherverwaltung benutzte [6]. Im Folgenden wird nur auf die grundlegenden Algorithmen eingegangen. Heute Speichermanagementsysteme beruhen auf diesen, wenn auch natürlich in optimierter Form. Man unterscheidet zwischen sogenannten Tracing-Algorithmen und reference counting. Tracing-Algorithmen bestimmen von Wurzelobjekten (engl. root set) ausgehend, welche Objekte im Speicher noch erreichbar sind. Alle Objekte auf die das nicht zutrifft können verworfen werden, da sie definitiv nicht mehr gebraucht werden (sie sind ja nicht mehr referenzierbar). Die Wurzelobjekte können z.b. in einer Liste gespeichert sein oder durch Scannen des Stacks bestimmt werden. 3

Im Folgenden wird zuerst aber reference counting beschrieben. 4.1 reference counting Wahrscheinlich die offensichtlichste Methode automatisches Speichermanagement zu betreiben ist alle Pointer/Referenzen zu zählen, die auf den jeweiligen Speicherbereich zeigen. In Worten: Für jedes Objekt im Speicher halte die Anzahl der Pointer, die auf dieses Objekt zeigen, irgendwo fest. Wird ein Pointer einem anderen Pointer zugewiesen wie hier in C i n t p, q ; ; p = q ;, dann erhöhe den Zähler des Speicherobjekts auf das q zeigt und erniedrige den Zähler des Speicherobjekts auf das p zeigt. Ist ein Zähler null kann der jeweilige Speicherbereich freigegeben werden. Werden vorher noch alle Pointer in diesem Speicherbereich abgearbeitet und deren Zähler dekrementiert, spricht man von rekursivem reference counting. Diese Methode wurde zum ersten Mal von George E. Collins in 1960 beschrieben [3]. Reference counting hat einige Vorteile aufgrund seiner Einfachheit. Nicht mehr gebrauchte Speicherbereiche werden sofort wieder freigegeben, es wird nur auf die wirklich benötigten Pointer zugegriffen und der nötige Rechenaufwand verteilt sich über die gesamte Ablaufzeit eines Programms. Simples reference counting kann jedoch nicht mit zyklischen Datenstrukturen umgehen, d.h. Objekte die sich selbst referenzieren. Jedoch kann der Algorithmus erweitert werden um mit diesen umzugehen. Des weiteren kann des Erhöhen und Erniedrigen des Zählers signifikanten Overhead erzeugen, was jedoch wieder durch Optimierungen vermieden werden kann. Reference counting wird in C++ bei sogenannten smart pointers zur automatischen Speicherverwaltung verwendet [2]. 4.2 mark-sweep Bei mark-sweep handelt es sich um einen sogenannten tracing-algorithmus. Ausgehend von Wurzelobjekten (Pointer in Registern, Stacks, globalen Variablen) markiert es die Speicherbereiche die erreihbar sind. Diese Speicherbereiche werden wieder nach Pointern zu Speicherbereiche durchsucht und dann diese markiert, usw. In der zweiten Phase (sweep) werden dann alle 4

5 Schluss Literatur [1] malloc(3) - Linux man page. http://man7.org/linux/man-pages/man3/ malloc.3.html. [Online; accessed 10-December-2014]. [2] The GNU C++ Library. https://gcc.gnu.org/onlinedocs/libstdc++/, 2008-2014. [Online; accessed 17-December-2014]. [3] George E. Collins. A method for overlapping and erasure of lists. Communications of the ACM, 3(12):655 657, December 1960. [4] Richard Jones, Antony Hosking, and Eliot Moss. The Garbage Collection Handbook: The Art of Automatic Memory Management. CRC Applied Algorithms and Data Structures. Chapman & Hall, January 2012. [5] Richard E. Jones. Garbage Collection: Algorithms for Automatic Dynamic Memory Management. Wiley, Chichester, July 1996. With a chapter on Distributed Garbage Collection by R. Lins. [6] John McCarthy et al. Lisp 1.5 Programmer s Manual, 1962. 5