Malloc Verständnis
-
SeppJ schrieb:
CrispyTurtleAlligator schrieb:
Gast3 schrieb:
google ist wirklich dein Freund und lesen macht nicht krank
http://www.cplusplus.com/reference/cstdlib/malloc/
*p = 99 setzt nicht den Zeiger sondern was anderes
Nicht den Zeiger sondern einfach den Wert von p auf 99?
p ist doch ein Zeiger...
Was genau tut *p=99 dann?
-
CrispyTurtleAlligator schrieb:
SeppJ schrieb:
CrispyTurtleAlligator schrieb:
Gast3 schrieb:
google ist wirklich dein Freund und lesen macht nicht krank
http://www.cplusplus.com/reference/cstdlib/malloc/
*p = 99 setzt nicht den Zeiger sondern was anderes
Nicht den Zeiger sondern einfach den Wert von p auf 99?
p ist doch ein Zeiger...
Was genau tut *p=99 dann?
Es verändert den Wert an der Stelle, auf die p zeigt.
-
SeppJ schrieb:
CrispyTurtleAlligator schrieb:
Was genau tut *p=99 dann?
Es verändert den Wert an der Stelle, auf die p zeigt.
... und wenn an der Stelle zufälligerweise schon eine 99 war, dann bleibt die sogar gleich!
-
int main(void) { /*a ist ein Zeiger auf einen Int. Nix besonderes. Zeigt aber derzeit auf Unsinn, weil nicht zugewiesen.*/ int*a; /*Das hier wäre UB. Könnte funktionieren. Könnte auch dein Programm abschmieren lassen.*/ /**a = 0;*/ /*Jetzt mal ein Zeiger mit Inhalt. Wir wollen aber nicht malloc machen, deswegen erstellen wir einen **int auf'm Stack.*/ int real; int*b = ℜ /*b zeigt jetzt auf real. Da kann man dann sowas machen, und real ist dann auch 99.*/ *b = 99; /*Jetzt setzen wir b auf 0. Den Zeiger, nicht den Wert dahinter*/ b = NULL; /*Und schon darfst du nicht mehr das hier machen*/ /**b = 99;*/ return 0; }
-
SeppJ schrieb:
Es verändert den Wert an der Stelle, auf die p zeigt.
Dann war mein Gedanke im ersten Beitrag doch korrekt, nur etwas unglücklich formuliert.
dachschaden schrieb:
int main(void) { /*a ist ein Zeiger auf einen Int. Nix besonderes. Zeigt aber derzeit auf Unsinn, weil nicht zugewiesen.*/ int*a; /*Das hier wäre UB. Könnte funktionieren. Könnte auch dein Programm abschmieren lassen.*/ /**a = 0;*/ /*Jetzt mal ein Zeiger mit Inhalt. Wir wollen aber nicht malloc machen, deswegen erstellen wir einen **int auf'm Stack.*/ int real; int*b = ℜ /*b zeigt jetzt auf real. Da kann man dann sowas machen, und real ist dann auch 99.*/ *b = 99; /*Jetzt setzen wir b auf 0. Den Zeiger, nicht den Wert dahinter*/ b = NULL; /*Und schon darfst du nicht mehr das hier machen*/ /**b = 99;*/ return 0; }
*a = 0; ist nicht möglich, da *a noch auf keine Adresse zeigt, richtig?
b = NULL setzt die Adresse, auf die B zeigt auf NULL, also leer, oder? Deshalb ist dann ein Zuweisen des Wertes 99 auf die Adresse, auf die *b zeigt, auch nicht mehr möglich. Richtig?
-
CrispyTurtleAlligator schrieb:
*a = 0; ist nicht möglich, da *a noch auf keine Adresse zeigt, richtig?
Zeiger sind auch nur Variablen. Was für einen Wert hat eine Variable auf dem Stack, die keinen Wert zugewiesen hat? Undefiniert. Möglich ist die Zuweisung schon, aber halt undefiniert. Deswegen auch UB (undefined behavior). Keine Garantie, was dann passiert.
CrispyTurtleAlligator schrieb:
b = NULL setzt die Adresse, auf die B zeigt auf NULL, also leer, oder?
"Leer" - nein. "Auf eine Adresse, auf die - von einem normalen Programm aus gesehen - Lesen und Schreiben verboten ist" - ja. Und das ist in jedem Fall besser, als einen uninitialisierten Zeiger zu haben.
CrispyTurtleAlligator schrieb:
Deshalb ist dann ein Zuweisen des Wertes 99 auf die Adresse, auf die *b zeigt, auch nicht mehr möglich. Richtig?
Noch mal, möglich ist viel. Aber die meisten BS garantieren dir, dass wenn du NULL ließt oder beschreibst, dass dein Programm dann abschmiert.
Eine Ausnahme ist Kernel-Code, aber da hast noch lange nichts mit zu tun.
-
dachschaden schrieb:
CrispyTurtleAlligator schrieb:
*a = 0; ist nicht möglich, da *a noch auf keine Adresse zeigt, richtig?
Zeiger sind auch nur Variablen. Was für einen Wert hat eine Variable auf dem Stack, die keinen Wert zugewiesen hat? Undefiniert. Möglich ist die Zuweisung schon, aber halt undefiniert. Deswegen auch UB (undefined behavior). Keine Garantie, was dann passiert.
CrispyTurtleAlligator schrieb:
b = NULL setzt die Adresse, auf die B zeigt auf NULL, also leer, oder?
"Leer" - nein. "Auf eine Adresse, auf die - von einem normalen Programm aus gesehen - Lesen und Schreiben verboten ist" - ja. Und das ist in jedem Fall besser, als einen uninitialisierten Zeiger zu haben.
CrispyTurtleAlligator schrieb:
Deshalb ist dann ein Zuweisen des Wertes 99 auf die Adresse, auf die *b zeigt, auch nicht mehr möglich. Richtig?
Noch mal, möglich ist viel. Aber die meisten BS garantieren dir, dass wenn du NULL ließt oder beschreibst, dass dein Programm dann abschmiert.
Eine Ausnahme ist Kernel-Code, aber da hast noch lange nichts mit zu tun.Danke für die großartige Hilfe!
-
Ab welcher Größe ist es denn sinnvoll dynamischen Speicher mit malloc(); zu nutzen?
-
CrispyTurtleAlligator schrieb:
Ab welcher Größe ist es denn sinnvoll dynamischen Speicher mit malloc(); zu nutzen?
Immer dann, wenn man es muss oder dann, wenn man es braucht
Auf solche Fragen gibt es eigentlich keine korrekte Antwort. Beziehungsweise, es gibt eine korrekte Antwort, aber sie ist bewusst vage:
a) Offensichtlicherweise, wenn die Größe dynamisch ist.
b) Wenn technische Gründe dafür sprechen, weil man schnell moven oder swappen möchte. Gleichzeitig soll der relative Overhead durch die Indirektion aber klein sein, damit die Performance bei normalen Zugriffen nicht unnötig leidet. Beides heißt, dass die gespeicherten Daten deutlich größer sein sollten als die nötigen Verwaltungsdaten, um den dynamischen Speicher zu verwalten. Aber wie groß ist "deutlich größer"? 2x? 10x? 1000x? Ich sag mal als Daumenwert 10-20x, also wenige hundert Bytes.
c) Wenn einen technische Gründe zwingen, etwa weil die Stackgröße begrenzt ist. Aber wie groß ist der Stack und wie viele Instanzen will ich haben? Ist alles sehr schwammig. Ich würde sagen, ein paar hundert Bytes sind hier wieder ein guter Daumenwert. Das gibt einem selbst in den restriktivsten annehmbaren Systemen ein paar tausend mögliche Instanzen und man hat angenehmerweise ungefähr den gleichen Cutoff wie bei b).
-
SeppJ schrieb:
CrispyTurtleAlligator schrieb:
Ab welcher Größe ist es denn sinnvoll dynamischen Speicher mit malloc(); zu nutzen?
Immer dann, wenn man es muss oder dann, wenn man es braucht
Auf solche Fragen gibt es eigentlich keine korrekte Antwort. Beziehungsweise, es gibt eine korrekte Antwort, aber sie ist bewusst vage:
a) Offensichtlicherweise, wenn die Größe dynamisch ist.
b) Wenn technische Gründe dafür sprechen, weil man schnell moven oder swappen möchte. Gleichzeitig soll der relative Overhead durch die Indirektion aber klein sein, damit die Performance bei normalen Zugriffen nicht unnötig leidet. Beides heißt, dass die gespeicherten Daten deutlich größer sein sollten als die nötigen Verwaltungsdaten, um den dynamischen Speicher zu verwalten. Aber wie groß ist "deutlich größer"? 2x? 10x? 1000x? Ich sag mal als Daumenwert 10-20x, also wenige hundert Bytes.
c) Wenn einen technische Gründe zwingen, etwa weil die Stackgröße begrenzt ist. Aber wie groß ist der Stack und wie viele Instanzen will ich haben? Ist alles sehr schwammig. Ich würde sagen, ein paar hundert Bytes sind hier wieder ein guter Daumenwert. Das gibt einem selbst in den restriktivsten annehmbaren Systemen ein paar tausend mögliche Instanzen und man hat angenehmerweise ungefähr den gleichen Cutoff wie bei b).Herzlichen Dank, damit gebe ich mich zufrieden!