420 likes | 541 Views
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.
E N D
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.
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.
malloc verlangt, daß man - durch den cast Operator (..) - den Datentyp angibt, auf den die Anfangsadresse des Speicherbereichs zeigt int main(){ int *pint; pint = (int *) malloc(3*sizeof(int)); // pint = (int *) malloc(12);} reserviert Speicher für 3 * Speicherbedarf(integer) 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)); Hier wird nachher der Anfang des dynamischen Speichers (in einem Zeiger) festgehalten. reserviert Speicher für... berechnet den Speicherbedarf von der Struktur dtraum : 3 · Speicherbedarf(integer) = 12 Byte Welchen Wert hat pr an dieser Stelle ? pr 0100 0100 ? Annahme: Die Variable pr werde an der Adresse 0100 gespeichert. anz Speicherelemente mit dem Datentyp struct dtraum
... 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 pr 0100 0100 ? gleiche 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; } ? 0500 ? ... ? 0504 ... ? 0508 ? ... ? 0512 ? ... ? Annahme: Speicherbereich beginnt bei Adresse 0500 0516 ? ... ? pr 0100 0100 0500 0520 ? Speicherreservierung für : 2 · sizeof(dtraum) = 2 · 3 · 4 Byte. ... ?
*(0500 + 0 · 12) ... 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; } ? 0500 ? ... ? 0504 ... ? 0508 ? ... ? 0512 ? ... ? 0516 ? ... ? pr 0100 0100 0500 0520 ? ... ?
*(0500 + 0 · 12) ... 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; } 0500 0 0 ... ? 0504 ... ? 0508 ? ... ? 0512 ? ... ? 0516 ? ... ? pr 0100 0100 0500 0520 ? ... ?
*(0500 + 0 · 12) ... 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; } 0500 0 0 ... ? 0504 ... ? 0508 ? ... ? 0512 ? ... ? 0516 ? ... ? pr 0100 0100 0500 0520 ? ... ?
*(0500 + 0 · 12) ... 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; } 0500 0 0 ... 0504 1 0 ... 0508 ? ... ? 0512 ? ... ? 0516 ? ... ? pr 0100 0100 0500 0520 ? ... ?
*(0500 + 0 · 12) ... 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; } 0500 0 0 ... 0504 1 0 ... 0508 ? ... ? 0512 ? ... ? 0516 ? ... ? pr 0100 0100 0500 0520 ? ... ?
*(0500 + 0 · 12) ... 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; } 0500 0 0 ... 0504 1 0 ... 0508 2 0 ... 0512 ? ... ? 0516 ? ... ? pr 0100 0100 0500 0520 ? ... ?
*(0500 + 1 · 12) ... 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; } 0500 0 0 ... 0504 1 0 ... 0508 2 0 ... 0512 ? ... ? 0516 ? ... ? pr 0100 0100 0500 0520 ? ... ?
*(0500 + 1 · 12) ... 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; } 0500 0 0 ... 0504 1 0 ... 0508 2 0 ... 0512 0 1 ... 0516 ? ... ? pr 0100 0100 0500 0520 ? ... ?
*(0500 + 1 · 12) ... 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; } 0500 0 0 ... 0504 1 0 ... 0508 2 0 ... 0512 0 1 ... 0516 ? ... ? pr 0100 0100 0500 0520 ? ... ?
*(0500 + 1 · 12) ... 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; } 0500 0 0 ... 0504 1 0 ... 0508 2 0 ... 0512 0 1 ... 0516 1 1 ... pr 0100 0100 0500 0520 ? ... ?
*(0500 + 1 · 12) ... 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; } 0500 0 0 ... 0504 1 0 ... 0508 2 0 ... 0512 0 1 ... 0516 1 1 ... pr 0100 0100 0500 0520 ? ... ?
*(0500 + 1 · 12) ... 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; } 0500 0 0 ... 0504 1 0 ... 0508 2 0 ... 0512 0 1 ... 0516 1 1 ... pr 0100 0100 0500 0520 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; } 0500 reservierten Speicher wieder freigeben 0 0 ... 0504 1 0 ... 0508 2 0 ... 0512 0 1 ... 0516 1 1 ... pr 0100 0100 0500 0520 2 1 ... free(pr);
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); } Was geschieht, wenn nach der Freigabe des reservierten Speichers auf diesen Speicher zugegriffen wird? pr->l=100; printf("%d", pr->l); 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; } Welchen Wert hat pr an dieser Stelle des Programms ? ? bedeutet: irgendein unbekannter, zufälliger Wert. Zum Beispiel: 0815 pr 0100 0100 ?
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; } 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! pr 0100 0100 0815
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; } 0815 Teil des 0816 0817 Betr. 0818 Syst. pr 0100 0100 0815
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; } 0815 0816 0 0 0 0 0817 0818 Dieser Teil des Betriebssystems wird überschrieben pr 0100 0100 0815
#include "stdafx.h"#include <malloc.h>struct dtraum{ int l; int b; int h;};int main(){ int i; 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;}