Dynamischer Speicher und Struktur. Beispiel: In einem Test-Programm werden die Anzahl, die Länge,...

Preview:

Citation preview

Dynamischer Speicher und

Struktur

Beispiel:

In einem Test-Programm werden die Anzahl, die Länge, Breite und Höhe mehrerer Räume gespeichert. Der Anwender gibt die Anzahl der abzuspeichernden Räume ein. Die Länge, Breite und Höhe werden vorläufig (zu Testzwecken) durch das Programm festgelegt.

Ein Raum wird durch folgende Struktur realisiert:

struct dtraum{ int l; int b; int h;};

Realisieren Sie das Programm durch ein Feld, dessen einzelne Elemente jeweils eine Struktur bilden.

#include "stdafx.h"#include <malloc.h>

struct dtraum{int l;int b;int h;

};

// gleich geht es weiter...

int main(){ int anz,i; struct dtraum v[1000];

printf("Anzahl eingeben =\n"); scanf("%d",&anz);

for(i=0;i<anz;i++){ v[i].l=i; v[i].b=i+10; v[i].h=i+20; }}

Welchen Nachteil hat dieses Programm bezüglich des Speicherplatzverbrauchs

Der Anwender kann mehr Speicher – als reserviert – verbrauchen.(z.B. bei Eingabe von 2000 für anz).

Dies ist dann “Unerlaubte Speicherbenutzung“Der Anwender kann weniger Speicher – als reserviert – verbrauchen

(z.B. bei Eingabe von 1 für anz).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 des Programmlaufs gemacht und heißt

deshalb dynamischer Speicher(reservierung).

Die Funktion malloc kann während der Laufzeit des Programms eine gewünschte Menge Speicher (vom Betriebssystem) organisieren. Welche Angabe braucht man dann, um auf diesen Speicher zuzugreifen ?

Man braucht die Anfangsadresse dieses reservierten Speicherbereichs.Die Funktion malloc liefert diese Anfangsadresse zurück.

Beispiel:

int main(){

int *pint;

pint = (int *) malloc(3*sizeof(int));

// pint = (int *) malloc(12);}

reserviert Speicher für 3 * Speicherbedarf(integer)

malloc verlangt, daß man - durch den cast Operator (..) - den Datentyp

angibt, auf den die Anfangsadresse des Speicherbereichs zeigt

nicht empfehlenswert: falls man weiß wieviel Speicher 3 Integer belegen, könnte man auch die Anzahl der Bytes direkt angeben

Anfangsadresse des reservierten Speichers

Realisieren Sie das vorige Programm, in dem die Räume in einem Feld abgespeichert wurden, durch die Verwendung von dynamischem Speicher.

#include "stdafx.h"#include <malloc.h>

struct dtraum{int l;int b;int h;

};

// gleich geht es weiter...

int main(){ int i; int anz=0; struct dtraum *pr; printf("Anzahl eingeben\n\n"); scanf("%d",&anz); pr = (struct dtraum *) malloc (anz*sizeof(struct dtraum));

reserviert Speicher für...

Hier wird nachher der Anfang des dynamischen Speichers (in einem

Zeiger) festgehalten.

Welchen Wert hat pr an dieser Stelle ?

anz Speicherelemente mit dem Datentyp struct dtraum

0100 ?0100pr

berechnet den Speicherbedarf von der Struktur dtraum : 3 · Speicherbedarf(integer) = 12 Byte

Annahme:Die Variable pr werde an der Adresse 0100 gespeichert.

... pr = (struct dtraum *) malloc (anz*sizeof(struct dtraum)); for(i=0;i<anz;i++){ (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

Annahme: anz = 2

0100 ?0100prgleiche Befehle, nur anders geschrieben

... pr = (struct dtrau (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

??

0504... ?0508

?

0512

0516

05200100 05000100pr

Speicherreservierung für : 2 · sizeof(dtraum) = 2 · 3 · 4 Byte.

?...

...

...

??

????

... ?

0500...

Annahme: Speicherbereich beginnt bei Adresse 0500

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

??

0504... ?0508

?

0512

0516

05200100 05000100pr

?...

...

...

??

????

... ?

0500...

*(0500 + 0 · 12)

0504... ?0508

?

0512

0516

0520

?...

...

...

??

????

... ?

0500... 0 0 ...

pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

*(0500 + 0 · 12)

0504... ?0508

?

0512

0516

0520

?...

...

...

??

????

... ?

0500...

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

0 0*(0500 + 0 · 12)

0504...0508

0512

0516

0520

?...

...

...

??

????

... ?

0500... 0 0

1 0

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

*(0500 + 0 · 12)

0504...0508

0512

0516

0520

?...

...

...

??

????

... ?

0500... 0 0

1 0

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

*(0500 + 0 · 12)

0504...0508

0512

0516

0520

...

...

...

?????

... ?

0500... 0 0

1 0

2 0

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

*(0500 + 0 · 12)

0504...0508

0512

0516

0520

...

...

...

?????

... ?

0500... 0 0

1 0

2 0

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

*(0500 + 1 · 12)

0504...0508

0512

0516

0520

...

...

...???

... ?

0500... 0 0

1 0

2 0

0 1

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

*(0500 + 1 · 12)

0504...0508

0512

0516

0520

...

...

...???

... ?

0500... 0 0

1 0

2 0

0 1

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

*(0500 + 1 · 12)

0504...0508

0512

0516

0520

...

...

...?

... ?

0500... 0 0

1 0

2 0

0 1

1 1

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

*(0500 + 1 · 12)

0504...0508

0512

0516

0520

...

...

...?

... ?

0500... 0 0

1 0

2 0

0 1

1 1

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

*(0500 + 1 · 12)

0504...0508

0512

0516

0520

...

...

...

...

0500... 0 0

1 0

2 0

0 1

1 1

2 1

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

*(0500 + 1 · 12)

0504...0508

0512

0516

0520

...

...

...

...

0500... 0 0

1 0

2 0

0 1

1 1

2 1

... pr = (struct dtraum (anz*sizeof(st for(i=0;i<anz;i++) (*(pr+i)).l=i;// (pr+i)->l=i;// pr[i].l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 05000100pr

free(pr);

reservierten Speicher wieder freigeben

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

pr = (struct dtraum *) malloc (anz*sizeof(struct dtraum)); if(pr != NULL){ // z.B. Anweisungen // siehe oben... free(pr); }

Wenn pr den Wert NULL (0) hat bedeutet dies:Vom Betriebssystem kann kein Speicher mehr reserviert werden, weil z.B. schon vorher im Programm viel Speicher reserviert wurde.

pr = (struct dtraum *) malloc (anz*sizeof(struct dtraum)); if(pr != NULL){ // Anweisungen // ... free(pr); }

pr->l=100;printf("%d", pr->l);

Was geschieht, wenn nach der Freigabe des reservierten Speichers auf diesen Speicher zugegriffen wird?

Es kann (muss aber nicht) zur Laufzeit eine Fehlermeldung erscheinen (übliche blaue Fenster...). Wenn keine Fehlermeldung erscheint, kann sich dieser Fehler später im Programm sehr unangenehm bemerkbar machen...

Was macht das gleiche Programm, aber ohne die Anweisung:

pr = (struct dtraum *) malloc (anz*sizeof(struct dtraum));

int main(){ int i; int anz=0; struct dtraum *pr; printf("Anzahl eingeben\n\n"); scanf("%d",&anz); for(i=0;i<anz;i++){ (*(pr+i)).l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 ?0100pr

Welchen Wert hat pr an dieser Stelle des Programms ?

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

int main(){ int i; int anz=0; struct dtraum *pr; printf("Anzahl eingeben\n\n"); scanf("%d",&anz); for(i=0;i<anz;i++){ (*(pr+i)).l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 08150100pr

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.

Als schlimmer Fall könnte an der Adresse 0815 zum Beispiel...

ein Teil des Betriebssystems stehen!

int main(){ int i; int anz=0; struct dtraum *pr; printf("Anzahl ein scanf("%d",&anz); for(i=0;i<anz;i++){ (*(pr+i)).l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 08150100pr

0815 Teildes

08170818 Syst.

0816Betr.

int main(){ int i; int anz=0; struct dtraum *pr; printf("Anzahl ein scanf("%d",&anz); for(i=0;i<anz;i++){ (*(pr+i)).l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; }

0100 08150100pr

0815

08170818

0816

Dieser Teil des Betriebssystems wird überschrieben

0 0 0 0

Hier das ganze Programm...

#include "stdafx.h"#include <malloc.h>

struct dtraum{int l;int b;int h;

};

int main(){ int i; int fehler=0; int anz=0; struct dtraum *pr;

printf("Bitte Anzahl der Raeume eingeben =\n"); scanf("%d",&anz); pr = (struct dtraum *) malloc (anz*sizeof(struct dtraum)); if(pr!=NULL){ for(i=0;i<anz;i++){ (pr+i)->l=i; (pr+i)->b=i+10; (pr+i)->h=i+20; } free(pr); }

if(pr==NULL) printf("Es gibt keinen freien Speicher mehr");

// Nur zum Test: Zugriff auf freigegebenen Speicher pr->l=100; printf("%d", pr->l); return 0;}

Übungsaufgaben:Siehe Aufgabenblatt

Recommended