![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() ![]()
Nun eigentlich ist dieses Kapitel nichts anderes als ein weiteres Kapitel zu den Zeigern. Nur anstatt wie in den vorangegangenen Kapiteln mit statischen Speicherbereichen zu hantieren wollen wir das ganze jetzt dynamisch machen. Dazu benötigen sie erst mal ein kurze Erklärung was ein Heap ist....
Diese Funktion mit der es Möglich ist während der Laufzeit unseres Programms für Variablen Speicherplatz zu reservieren lautet...
Erst haben wir eine int-Zeiger definiert. Anschließend haben wir für unsern Zeiger mit...
![]() NULL - Zeiger: Der NULL - Zeiger wird zurückgeliefert wenn malloc nicht mehr genügend zusammenhängenden Speicher finden kann. Der NULL - Zeiger ist ein vordefinierter Zeiger dessen Wert sich vom regulären Zeigern unterscheidet. Man verwendet den NULL - Zeiger vorwiegend bei Funktionen die eine Zeiger als Rückgabewert liefern als Anzeige eines Fehlers. Wie im Programm gesehen steht die Funktion malloc in der Headerdatei <stdlib.h Bei einem Aufruf von malloc muss die Anzahl der zu reservierenden Bytes angegeben werden. Damit ist die Größe der Objekts gemeint das durch den Zeiger referenziert werden soll. Sie können die Größe auch mit numerischen Werten selbst bestimmen wie z.B..... p=(int *)malloc(sizeof(2)); Hier also 2 Bytes für eine int - Zeiger. Aber was machen sie wenn sie das Programm auf ein anderes System portieren wollen? Daher ist es oft besser die Größe des Zielobjektes vom Compilers selbst bestimmen zu lassen wie wir es oben im Programm gemacht haben. Sie haben 3 Möglichkeiten der dynamischen Speicherzuweisung... 1.Als Numerische Konstante: p=(int *)malloc(sizeof(2)); Nachteil habe ich eben erwähnt. 2. Die Angabe des Types von sizeof: p=(int *)malloc(sizeof(int)); Diese Möglichkeit ist hat nur einen Nachteil. Was wenn sie anstatt int auf einmal double - Werte wollen. Sie müssen mühsam alle Speicherzuweisungen umändern in... p=(double *)malloc(sizeof(double)); ...oder aber sie haben die Möglichkeit... 3. Den derferenzierten Zeiger selber für den sizeof - Operator zu verwenden. p=(double *)malloc(sizeof(*p)); Aber Achtung wehe dem sie Vergessen den Dereferenzierungsoperator '*' wie im folgendem Programm....
Wenn sie "Glück" haben stürzt ihnen das Programm ab. Wenn sie Pech haben funktioniert das Programm und gibt sogar die richtigen Zahlen aus. Aber das wäre dann purer Zufall. Denn ohne die Dereferenzierungsoperatoren wird nicht ein double - Wert an malloc übergeben, sondern die Größe des Zeigers. Und der ist üblicherweise 4 Bytes anstatt der Erforderlichen 8 Bytes
groß. Wenn jetzt zufällig ein anderer Wert an dieser Adresse in dem Heap hinkommt, ist die vorhersage für den Verlauf des Programms nicht absehbar. Man spricht von einer sogenannten Überlappung der Speicherbereiche.
Aber auch hier muss ich sie warnen. Mittels free() wird zwar der zugewiesene Speicher als frei markiert, aber p zeigt immer noch auf die Ursprüngliche Speicherstelle. Hier ein Beispiel worauf ich hinaus will....
Wenn sie wirklich sichergehen wollen das in unserem Beispiel der Pointer '*p' nichts mehr zurückgibt so müssen sie ihm nach 'free(p)' die Adresse von dem NULL-Zeiger übergeben....
....durch die Speicherallocation.......
![]() Hier das ganze nochmals Bildlich. Nun Anhand diesem Beispiels kann man aber auch Erkennen das wir Speicherplatz verschwenden. Auch wenn heutzutage die Speicher Überdimensioniert sind kann sich das auf Dauer schlecht auf die Performance auswirken. Folglich sollten wir nur soviel Speicher reservieren wie wir auch wirklich benötigen......
Natürlich könnte man das ganze auch in ein Anweisung packen.....
Nur begehen wir dabei einen der meistgemachten Fehler mit malloc.
Wir überprüfen hier nicht den Rückgabewert von malloc. Es ist
nicht immer gesagt das auch wirklich Speicherplatz reserviert wurde.
Dann auch hier gilt: Alles was schief gehen KANN, wird auch mal
schiefgehen!!!
Also vergessen sie niemals, wenn sie Speicher allokieren, den
Rückgabewert zu überprüfen, ob die Allokierung erfolgreich verlief. ![]() ![]() ![]() |