+ All Categories
Home > Documents > Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem...

Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem...

Date post: 05-Apr-2015
Category:
Upload: leonhardt-schlott
View: 102 times
Download: 0 times
Share this document with a friend
35
Dynamischer Speicher
Transcript
Page 1: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

DynamischerSpeicher

Page 2: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

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

Page 3: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

Beispiel:

Page 4: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

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 dieser Speicherplatz automatisch (ohne Zutun des Programmmierers) wieder freigegeben.

Page 5: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

Beispiel:Man will die von einem Anwender (über Tastatur eingegebene) bestimmte

Anzahl von Zahlen in einem Feld abspeichern.

Page 6: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

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 ist dann Speicherverschwendung.

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 der Programmlaufs gemacht und heißt

deshalb dynamischer Speicher(reservierung).

Page 7: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

Realisierung in C++

Page 8: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

int main(){ int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i<anz; i++){ cin >> zahl; *(panf+i)=zahl; } // panf[i]=zahl delete panf;}

eingelesener Wert wird in anz gespeichert

für ein Feld von anz integer-Werten

panf zeigt auf das erste Element des Feldes

Mögliche (gleichwertige) Formen des Zugriffs

Reserviert dynamisch Speicher:

gibt Speicher wieder frei

Page 9: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

020...

int main(){ int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i<anz; i++){ cin >> zahl; *(panf+i)=zahl; }//...

... ...panf

WelchenWert hatpanf an dieser Stelle des Programmms ?

Annahme: anz = 2

In der 1. Spalte stehen die Adressen der Variablen

In der 2. Spalte stehen die Inhalte der Adressen (Werte der Variablen)

Page 10: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

020...

?... ...

panf

int main(){ int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i<anz; i++){ cin >> zahl; *(panf+i)=zahl; }//...

Was veranlasst diese Anweisungen ?

Es wird im Arbeitsspeicher Platz für 2 integer-Zahlen reserviert und die (Anfangs)Adresse dieses Speicherbereichs der Variable panf zugewiesen.

Auf die (Anfangs)Adresse dieses Speicherbereichs hat der Programmierer keinen Einfluß. Diese legt der Compiler bzw. Programmlader fest.

Page 11: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

020...

0700... ...

panf

int main(){ int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i<anz; i++){ cin >> zahl; *(panf+i)=zahl; }//...

0700 ??

??

Speicherreservierung für 2 integer-Zahlen,die z.B. bei der Adresse 0700 beginnen

?

zeigt auf:

???

Annahme:Die 1. über Tastatur eingegebene Zahl sei 17 und die 2. eingegebene Zahl sei 13.Was bewirkt dann jeweils (insgesamt zweimal) diese Anweisung ?

Page 12: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

020...

0700... ...

panf

int main(){ int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i<anz; i++){ cin >> zahl; *(panf+i)=zahl; }//...

0700

0704

0017

0013

Page 13: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

Man kann auch für Objekte dynamisch Speicher

allokieren:

Page 14: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

int main(){ Konto *pk; pk = new Konto; // Anweisungen delete pk;}

new reserviert dynamisch Speicher. Die Anfangsadresse des dynamischen Speichers wird in einem Zeiger festgehalten, damit man später darauf zugreifen kann. Zusätzlich wird automatisch der Konstruktor aufgerufen.

Falls kein Speicher mehr allokiert werden kann, bekommt pk den Wert NULL, den sogenannten Nullzeiger, zugewiesen. Dieser Nullzeiger zeigt auf kein Objekt !

delete gibt den dynamisch erzeugten Speicher wieder frei.Zusätzlich wird automatisch der Destruktor aufgerufen. Falls pk gleich NULL ist, wird keine Operation ausgeführt.

In der schließenden Klammer } wird kein Destruktor aufgerufen, da pk eine Zeigervariable ist.

Page 15: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

Ein weiteres Beispiel:

Page 16: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

Die Klasse Bank hat u.a. das Attribut art (Datentyp char), in dem gespeichert ist, ob ein

Konto einem Mitarbeiter gehört (‘M‘), oder einer fremden Person (‘F‘).

Page 17: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

Die zugehörigen Methoden, die diesen Modus setzen bzw. lesen heissen (aus Platzgründen verkürzt):

setM getM

Page 18: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

class Bank { private: char art; ... public: void setM(...) ... };

In art wird die Art des Mitarbeiters gespeichert, also: 'M' oder 'F'

Page 19: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

Annahme:Ein Objekt der Klasse Bank sei 100 Byte groß.

Page 20: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); pi = new int; pk = new Konto; pkk = new Konto[anz]; ...

Hier wird nachher jeweils der Anfang des dynamischen Speichers (in einem

Zeiger) festgehalten.

einen integer-Wert

Zufallszahl

die folgenden 3 Befehle reservieren Speicher für:

für ein Objekt der Klasse Konto

für ein Feld von anz Objekten der Klasse Konto

Page 21: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

0100...0120pk... ...0140pkk

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); pi = new int; pk = new Konto; pkk = new Konto[anz];

... ...pi

Welchen Wert haben pi, pk, pkkan dieser Stelle des Programmms ?

Annahmen: anz = 2Speicherplatz Konto: 100 Byte

In der 1. Spalte stehen die Adressen der Variablen

In der 2. Spalte stehen die Inhalte der Adressen (Werte der Variablen)

Page 22: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

100...

?

120 ?pk... ...140 ?pkk

... ...pi

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); pi = new int; pk = new Konto; pkk = new Konto[anz];

Was veranlasst diese Anweisung ?

Es wird im Arbeitsspeicher Platz für eine integer-Zahl reserviert und die (Anfangs)Adresse dieses Speicherbereichs der Variable pi zugewiesen.

Auf die (Anfangs)Adresse des reservierten Speichers hat der Programmierer keinen Einfluß. Dies legt der Compiler (bzw. Programmlader fest).

Page 23: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

0100...

0500

0120 ?pk... ...0140 ?pkk

... ...pi

int main(){int anz;int *pi;Konto *pk, *pkk;anz = rand();pi = new int;pk = new Konto;pkk = new Konto[anz];

0500 ??

?

Speicherreservierung für ein integer, das

z.B. bei der Adresse 0500 beginnt

?

zeigt auf:

Page 24: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

0100...

0500

0120 0504pk... ...0140 ?pkk

... ...pi

int main(){int anz;int *pi;Konto *pk, *pkk;anz = rand();pi = new int;pk = new Konto;pkk = new Konto[anz];

0500 ?

??

?

Speicherreservierung für ein Objekt der

Klasse Konto (hier: 100 Byte)

?

zeigt auf:

...

...?

0504

Page 25: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

0100...

0500

0120 0504pk... ...0140 0604pkk

... ...pi

int main(){int anz;int *pi;Konto *pk, *pkk;anz = rand();pi = new int;pk = new Konto;pkk = new Konto[anz];

0504 ?

??

...Speicherreservierung für ein Feld der Länge 2 mit

Objekten der Klasse Konto (hier: 2*100 Byte) ...

zeigt auf:

...

...?

0704 ?......?

0604

Page 26: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

0100...

0500

0120 0504pk... ...0140 0604pkk

... ...pi

*pi = 5;(*pk).setM('M');// pk->setM('M');(*(pkk+1)).setM('F');// pkk[1].setM('F');// (pkk+1)->setM('F');delete pi;delete pk;delete [] pkk;}

0504 ?

??

...

...

...

...?

0704 ?......?

0604

Page 27: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

0100...

0500

0120 0504pk... ...0140 0604pkk

... ...pi

*pi = 5;(*pk).setM('M');// pk->setM('M');(*(pkk+1)).setM('F');// pkk[1].setM('F');// (pkk+1)->setM('F');delete pi;delete pk;delete [] pkk;}

0500

0005

gleiche Befehle, nur anders geschrieben

Bemerkung:Die Zahl (hier 5) wird in den zur Verfügung stehenden 32 Bit gespeichert (in welchen Bits die einzelnen Ziffern der Zahl stehen, interessiert uns hier nicht).

Page 28: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

0100...

0500

0120 0504pk... ...0140 0604pkk

... ...pi

*pi = 5;(*pk).setM('M');// pk->setM('M');(*(pkk+1)).setM('F');// pkk[1].setM('F');// (pkk+1)->setM('F');delete pi;delete pk;delete [] pkk;}

0504 ‘M‘

0604??

...

...

...

...?

0704 ?......?

gleiche Befehle, nur anders geschrieben

Page 29: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

0100...

0500

0120 0504pk... ...0140 0604pkk

... ...pi

*pi = 5;(*pk).setM('M');// pk->setM('M');(*(pkk+1)).setM('F');// pkk[1].setM('F');// (pkk+1)->setM('F');delete pi;delete pk;delete [] pkk;}

0504 ‘M‘

0604??

...

...

...

...?

0704 ‘F‘......?

Page 30: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

Was macht das gleiche Programm, aber ohne die folgenden Anweisungen:

pi = new int;pk = new Konto;pkk = new Konto[anz];

Page 31: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); // pk->setM('M'); (*(pkk+1)).setM('F'); // pkk[1].setM('F'); // (pkk+1)->setM('F'); ...

Welchen Wert hat pi z.B. an dieser Stelle des Programms ?

Page 32: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F');

0100...

?

0120 ...pk... ...0140 ...pkk

... ...pi

? bedeutet:irgendein unbekannter, zufälliger Wert.Zum Beispiel: 0815

Page 33: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F');

0100...

0815

0120 ...pk... ...0140 ...pkk

... ...pi

Was steht an der Adresse 0815 im Arbeitsspeicher ?

Der Programmier weiß es nicht, denn er hat an dieser Adresse keinen Speicherplatz reservieren lassen und diesen entsprechend belegt.

Im "schlimmsten" Fall könnte an der Adresse 0815 zum Beispiel...

Ein Teil des Betriebssystems beginnen !

Page 34: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F');

0100...

0815

0120 ...pk... ...0140 ...pkk

... ...pi

0815 Teildes

Syst.Betr.

Page 35: Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F');

0100...

0815

0120 ...pk... ...0140 ...pkk

... ...pi

0815 50

00

Dieser Teil des Betriebssystems wird überschrieben

Analoges gilt auch für die folgenden Anweisungen


Recommended