Dynamischer Speicher. Ein Vergleich aus dem täglichen Leben...

Slides:



Advertisements
Ähnliche Präsentationen
Einführung in die Programmiersprache C/C++
Advertisements

Einführung in die Programmiersprache C/C++
Funktionen, Felder und Parameter-übergabe
Funktionen.
Forschungszentrum caesar
Funktionen und Module Einführung anhand des Beispiels Wörter sortieren Timm Grams Fachhochschule Fulda Fachbereich Elektrotechnik und Informationstechnik.
Sortieren I - Bubblesort -
der Universität Oldenburg
Java: Dynamische Datentypen
Indirekte Adressierung
FH-Hof Indirekte Adressierung Richard Göbel. FH-Hof Einfache Speicherung von Daten Eine "einfache" Deklaration definiert direkt eine Speicherplatz für.
Java: Referenzen und Zeichenketten
SWITCH - Anweisung.
Datentyp- umwandlung. Literale sind: Bezeichner mit einem festen Wert wie z.B:
Klassenvariable (auch Klassendaten bzw. statische Attribute genannt) und statische Methoden.
Dateien. Eine Datei wird in C++ als ein Stream, also als ein Objekt einer bestimmten Klasse dargestellt.
Strukturen. In einer Struktur kann eine beliebige Anzahl von Komponenten (Daten) mit unterschiedlichen Datentypen (im Gegensatz zu Feldern) zusammengefaßt.
ARRAY oder FELD oder VEKTOR
Funktionen.
Ein Beispiel in Java.
Dynamisches Array als "verkettete Liste". Ein Vergleich.
Dynamischer Speicher und Struktur
Pointer. Grundsätzliches: Im Arbeitsspeicher werden Daten gespeichert. Um auf die Daten eindeutig zugreifen zu können, werden diesen Daten Adressen zugeordnet.
Klassenvariable. Da man für jede Kuh bzw. jede Henne auf dem Markt den gleichen Preis für ein Liter Milch, bzw. den gleichen Preis für ein Ei bekommt,
Konstruktoren.
WHILE - Anweisung.
Objekte werden als Adressen (Referenzen) übergeben. Dies führt manchmal zu unerwarteten Ergebnissen...
Parameterübergabe von zweidimensionalen Feldern in Funktionen.
Programmier-sprache C Weiter mit PP..
Polymorphie (Vielgestaltigkeit)
Polymorphie (Vielgestaltigkeit)
Objekte und Arbeitsspeicher
V AdresseWert public static void main(...){ int[] v; v=new int[2]; } Was veranlasst diese Anweisung im Arbeitsspeicher ? Es wird im Arbeitsspeicher.
FOR Anweisung.
Felder sortieren. Aufgabe: Die Zahlen eines Feldes sollen der Größe (zuerst die kleinste Zahl) nach sortiert werden.
Der Präprozessor. Bevor der Compiler das Programm in Maschinencode übersetzt (nur dieser kann von der CPU, dem Herz des Computers, bearbeitet werden)
FOR Anweisung. Aufgabe : Ausgabe aller ganzen Zahlen von 0 bis 100 auf dem Bildschirm.
DO...WHILE Anweisung.
Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.
ARRAY oder FELD oder VEKTOR
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 7 Claudio Moraga, Gisbert Dittrich FBI Unido
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
Verkettete Liste Visualisierung. New-Operator Mit dem New-Operator kann zur Laufzeit (dynamisch) Speicherplatz reserviert und angelegt werden Vorteil:
Arrays,Strings&Pointer in C/C++
EDV Parallelprogrammierung1 Parallelprogrammierung mit JAVA.
Einfach verkettete Listen (OOP)
Einführung in die Programmiersprache C 1
Informatik Grundlagen, WS04, Seminar 11
Programmieren in C Zeichen-/Stringfunktionen Dynamischer Speicher
Excel 97 Einführung - Start -.
Einführung in die Programmiersprache C 3.Tag Institut für Mathematische Optimierung - Technische Universität Braunschweig.
Einführung in die Programmiersprache C 4
Dynamische Datentypen
Variablenkonzept Klassisch, in Java Basistyp
Informatik Grundlagen, WS04, Seminar 7
Programmieren in C Grundlagen C 2
w. : sechs Tage vs. for six days w how much wieviel, how many. : wieviele Tage?(=how many days)
Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen.
early binding (frühe Bindung) late binding (späte Bindung)
Informatik I : Software höhere Programmiersprachen Java Klassen: hat Methoden (Funktionen) und Daten (Variablen) es kann mehrere Klassen geben nur eine.
C Tutorium – Memory Management – Knut Stolze. 2 Agenda Einführung in die Speicherverwaltung Stack vs. Heap Malloc Free Sizeof Tipps/Hinweise.
Funktionen. Aufgabe : Eingabe zweier Zahlen ---> Minimum bestimmen Dann nochmals Eingabe zweier Zahlen ---> Minimum bestimmen.
Dynamisches Array als "verkettete Liste". Ein Vergleich.
Pointer. Grundsätzliches: Im Arbeitsspeicher werden Daten gespeichert. Um auf die Daten eindeutig zugreifen zu können, werden diesen Daten Adressen zugeordnet.
Funktionen, Felder und Parameter- übergabe. Funktionsaufruf mit Feld als Parameter: Parameter = Name des Feldes.
Tutorium Software-Engineering SS14 Florian Manghofer.
Strukturen (Eigenschaften) Strukturen dienen zur Zusammenfassung mehrerer Komponenten verschiedener Typen zu einer Einheit, die dann mit gemeinsamen Namen.
Konstruktoren.
Dynamisches Array als "verkettete Liste"
Arrays in C Ein Array ist eine Variable, die aus einer Anzahl von Elementen des gleichen Datentyps besteht, die aufeinanderfolgend im Speicher liegen.
 Präsentation transkript:

Dynamischer Speicher

Ein Vergleich aus dem täglichen Leben...

Die Klasse BKI1 (20 Schüler) will in einem Jahr Urlaub (evtl. mit den bis dort existierenden neuen Freunden) in der Südsee machen und bucht deshalb vorsorglich schon jetzt Zimmer in einem Hotel. Wieviel Zimmer sollen in dem Hotel reserviert, also schon heute gebucht werden?

Fall 1: Es werden nur 20 Zimmer reserviert. Die neuen Freunde müssen deshalb in dem Hotel nicht reservierte Zimmer belegen. Dies kann zu durch äußere Gewalteinwirkung verursachten körperlichen Fehlfunktionen der neuen Freunde führen, wenn sie z.B. in schon (von anderen Personen) reservierten Zimmern übernachten.

Fall 2: Es werden mehr als 20 Zimmer reserviert (z.B. 100). Falls es bis dort dann keine neuen Freunde gibt, oder einige Schüler urplötzlich einen Fahrrad-Urlaub in Holland machen (und deswegen den Südsee-Urlaub absagen), werden reservierte Zimmer nicht belegt. Dies führt zu Geldverschwendung.

Zurück zur Programmiersprache C

In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen wird (nach dem Aufruf der Funktion), wird dieser Speicherbereich automatisch wieder freigegeben (nicht mehr reserviert).

Beispiel:

void f(){ int myfeld[10]; //... } int main(){ f(); //... } Erst wenn f aufgerufen wird, wird Speicher für myfeld auf dem Stack reserviert. Wieviel Byte sind dies ? 10 * Speicherbedarf (integer) Nach dem Aufruf wird der für int myfeld[10 ] reservierte Speicherbereich automatisch wieder freigegeben.

Beispiel: Man will die von einem Anwender bestimmte Anzahl von Zahlen in einem Feld abspeichern.

int main(){ int myfeld[1000]; //... } Welchen Nachteil hat dies bezüglich des Speicherplatzverbrauchs Der Anwender kann weniger Speicher – als reserviert – verbrauchen (z.B. bei Eingabe nur einer Zahl). Dies nennt man dann Speicherverschwendung. Der Anwender kann mehr Speicher – als reserviert – verbrauchen (z.B. bei Eingabe von 2000 Zahlen). Dies nennt man dann Überschreiben nicht reservierten Speichers.

Um dies zu vermeiden kann der Anwender – während der Laufzeit des Programms – so viel Speicher reservieren, wie er benötigt. Im Gegensatz zum Beispiel oben wird diese Reservierung nicht beim Compilieren, sondern während des Programmlaufs gemacht und heißt deshalb dynamischer Speicher(reservierung).

Realisierung in C

#include "stdafx.h" #include

int main(){ int anz, zahl, i; int *panf; printf("Anzahl eingeben:"); scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; // panf[i]=zahl; } eingelesener Wert wird in anz gespeichert für anz integer-Werte panf zeigt auf das erste Element des reservierten Speichers alternativ möglich (gleichbedeutend): reserviert dynamisch Speicher... sizeof berechnet den Speicherbedarf. Bei MS-VC++: Speicherbedarf(integer) = 4 Byte Annahme: anz = 2 Dieser cast-Operator gibt an, dass auf einen integer-Wert gezeigt wird.

int main(){ int anz, zahl,i; int *panf; printf("Anzahl eingeben:"); scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; // panf[i]=zahl; }... eingelesener Wert wird in anz gespeichert für anz integer-Werte panf zeigt auf das erste Element des reservierten Speichers alternativ möglich (gleichbedeutend): reserviert dynamisch Speicher... sizeof berechnet den Speicherbedarf. Bei MS-VC++: Speicherbedarf(integer) = 4 Byte Annahme: anz = 2 Wichtig: Der reservierte Speicher ist zusammenhängend und hat deshalb keine Lücken. Wenn man also die erste Adresse und die Größe des reservierten Speichers kennt, weiß man alle reservierten Speicherzellen.

//... siehe letzte Folie scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } free(panf); } 0700? panf Welchen Wert hat panf an dieser Stelle ? Annahme: Die Variable panf werde an der Adresse 700 gespeichert.

... scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } free(panf); } panf ? ? ? 0204 ? 0206 ? ? ? ? Speicherreservierung mit malloc für : 2 · sizeof(int) = 2 · 4 Byte = 8 Byte. Annahme: Speicherbereich beginnt bei Adresse 0200

... scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } free(panf); } panf ? ? ? 0204 ? 0206 ? ? ? ? Annahme: zahl =1000

... scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } free(panf); } panf ? ? ? 0204 ? 0206 ? ? ? ? *( · 4) Annahme: zahl =1000

... scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } free(panf); } panf ? ? ? ? Annahme: zahl =1000 *( · 4) Bemerkung: Wenn die Variable zahl statt 1000 den Wert hätte, dann würde in den 4 Byte an den Adressen 200 bis 203 gespeichert werden.

... scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } free(panf); } panf ? ? ? ? Annahme: zahl =2000

... scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } free(panf); } panf ? ? ? ? *( · 4) Annahme: zahl =2000

... scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } free(panf); } panf *( · 4) Annahme: zahl =2000

... scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } free(panf); } panf

... scanf("%d", &anz); panf = (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } free(panf); } panf gibt reservierten Speicher wieder frei.

In panf wird die Anfangsadresse des reservierten Speichers zurückgegeben. Was geschieht aber, wenn der Programmierer "Nimmersatt" mehr Speicher vom Betriebssytem will, als dieses zur Verfügung hat? Welche Anfangsadresse soll es zurückgeben? panf = (int *) malloc (anz*sizeof(int));

Es darf keine Anfangsadresse zurückgegeben werden. Es muss also einen bestimmten Wert geben, der von allen anderen Zeigerwerten (Adressen) verschieden ist und der nicht die Adresse irgendeiner Variablen enthält: der sogenannte "Null- Zeiger" (Nullpointer) mit dem Wert NULL panf = (int *) malloc (anz*sizeof(int));

Es besteht ein großer Unterschied zwischen dem Nullpointer und dem nicht initialisierten Pointer: Für den Nullpointer ist garantiert, dass er nirgendwohin zeigt, ein nicht initialisierter Zeiger hingegen kann überallhin zeigen. Über einen Nullpointer kann kein Zugriff erfolgen (also *NULL nicht möglich). panf = (int *) malloc (anz*sizeof(int));

WICHTIG: Die Verwendung von malloc sollte deshalb immer wie folgt geschehen:

panf = (int *) malloc (anz*sizeof(int)); if(panf != NULL){ // Anweisungen //... free(panf); } panf gleich NULL bedeutet: Vom Betriebssystem kann kein Speicher mehr reserviert werden, weil z.B. schon vorher im Programm viel Speicher reserviert wurde. versuche vom Betriebssystem Speicher zu reservieren

panf = (int *) malloc (anz*sizeof(int)); if(panf != NULL){ // Anweisungen //... free(panf); } Wenn der Speicher nicht freigegeben wird und man in diesem Programm nochmals Speicher reservieren will, kann es sein, dass kein freier Speicher mehr zur Verfügung steht. Hätte man dagegen den alten Speicher wieder freigegeben, könnte das Betriebssystem diesen wieder vergeben! Warum soll dieser Speicher wieder freigegeben werden?

Ein Vergleich: Angenommen ein Hotel hat 10 Zimmer und nach der Beendigung des Urlaubs wird ein Hotelzimmer nicht wieder (für eine Neureservierung) freigegeben. Nach wie viel Vermietungen muss der Hotelbesitzer dann ein neues Hotel kaufen, um wieder Zimmer vermieten zu können?

Nach 10 Vermietungen ! Was wäre deshalb eine bessere Strategie, um einen teuren Hotelkauf zu vermeiden?

Jedes Hotelzimmer (evtl. nach einer Grundreinigung) wieder neu zu einer Reservierung freizugeben (d.h. es wieder neu zu vermieten).

Was macht das gleiche Programm, aber ohne die Anweisung: panf = (int *) malloc (anz*sizeof(int));

int main(){ int anz, zahl,i; int *panf; printf("Anzahl eingeben:"); scanf("%d", &anz); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } 0100? panf ? bedeutet: irgendein unbekannter, zufälliger Wert. Zum Beispiel: 0815 Welchen Wert hat panf an dieser Stelle des Programms ? Annahme: zahl = 13 *( · 4) 13

int main(){ int anz, zahl,i; int *panf; printf("Anzahl eingeben:"); scanf("%d", &anz); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; } Was steht an der Adresse 0815 im Arbeitsspeicher ? Der Programmierer weiß es nicht, denn er hat an dieser Adresse keinen Speicherplatz reservieren lassen und diesen entsprechend belegt. In einem schlimmen Fall könnte an der Adresse 0815 zum Beispiel... ein Teil des Betriebssystems stehen ! *( · 4) panf 13

int main(){ int anz, zahl,i; int *panf; printf("Anzahl ein scanf("%d", &anz); for(i=0; i<anz; i+ scanf("%d", &zah *(panf+i)=zahl; } 0815Teil des Syst. Betr. *( · 4) panf 13

int main(){ int anz, zahl,i; int *panf; printf("Anzahl ein scanf("%d", &anz); for(i=0; i<anz; i+ scanf("%d", &zah *(panf+i)=zahl; } 0815 Dieser Teil des Betriebssystems wird überschrieben !!!! *( · 4) panf 13

Was macht das gleiche Programm, aber ohne die Zuweisung panf = also nur: (int *) malloc (anz*sizeof(int)); Mit malloc wird ja Speicher reserviert...

int main(){ int anz, zahl,i; int *panf; printf("Anzahl eingeben:"); scanf("%d", &anz); (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; // panf[i]=zahl; } reserviert dynamisch Speicher 8 Byte Was veranlasst diese Anweisung? (Annahme anz = 2)

int main(){ int anz, zahl,i; int *panf; printf("Anzahl eingeben:"); scanf("%d", &anz); (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; // panf[i]=zahl; } Welchen Wert hat panf an dieser Stelle des Programms ? Annahme: zahl = ? panf ? bedeutet: irgendein unbekannter, zufälliger Wert. Zum Beispiel: 0815 *( · 4) 13

int main(){ int anz, zahl,i; int *panf; printf("Anzahl eingeben:"); scanf("%d", &anz); (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; // panf[i]=zahl; } panf Was steht an der Adresse 0815 im Arbeitsspeicher ? Der Programmierer weiß es nicht, denn er hat an dieser Adresse keinen Speicherplatz reservieren lassen und diesen entsprechend belegt. In einem schlimmen Fall könnte an der Adresse 0815 zum Beispiel... ein Teil des Betriebssystems stehen ! 13

int main(){ int anz, zahl,i; int *panf; printf("Anzahl eingeben:"); scanf("%d", &anz); (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; // panf[i]=zahl; } panf 0815Teil des Syst. Betr. 13

int main(){ int anz, zahl,i; int *panf; printf("Anzahl eingeben:"); scanf("%d", &anz); (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; // panf[i]=zahl; } panf

int main(){ int anz, zahl,i; int *panf; printf("Anzahl eingeben:"); scanf("%d", &anz); (int *) malloc (anz*sizeof(int)); for(i=0; i<anz; i++){ scanf("%d", &zahl); *(panf+i)=zahl; // panf[i]=zahl; } panf Mit malloc wurde zwar Speicher reserviert, doch leider nirgends (in keiner Variablen wie z.B. panf) festgehalten, wo dieser reservierte Speicher beginnt. Der reservierte Speicher kann also nicht benutzt werden (Speicherleiche). Dagegen wurde nicht reservierter Speicher benutzt, was zu schweren Problemen führt.