Jo schrieb:> so wie hier gezeigt mit malloc korrekt?
Du musst noch pruefen, ob du auch speicher bekommen hast.
1
ptr_test=(test*)malloc(sizeof(test));
2
3
if(ptr_test==NULL){
4
/* es konnte kein Speicher reserviert werden */
5
/* was machst du, wenn du keinen Speicher */
6
/* bekommen hast? */
7
}
Ansonsten passt das.
Bei
1
ptr_test=(test*)malloc(sizeof(test));
scheiden sich die Geister, ob man den Rueckgabewert von malloc nun
casten sollte oder nicht. In C++ musst du casten, in C kannst du casten,
musst du aber nicht.
Beachte, dass bei malloc der Speicher nicht initialisiert wird!
Wenn du calloc benutzt, dann wird der Speicher mit 0 initialisiert.
http://www.cplusplus.com/reference/cstdlib/calloc/
Jo schrieb:> ist diese Speicherreservieren so wie hier gezeigt mit malloc korrekt?
ich würde folgendes bevorzugen:
1
ptr_test=malloc(sizeof(*ptr_test));
Grund:
wenn du den Pointertyp von "ptr_test" änderst, musst du bei meiner
Variante das Malloc nicht anpassen - kannst es also auch nicht
vergessen.
bezüglich:
Kaj schrieb:> scheiden sich die Geister, ob man den Rueckgabewert von malloc nun> casten sollte oder nicht. In C++ musst du casten, in C kannst du casten,> musst du aber nicht.
in c++ könnte man aber auch direkt `new` benutzen - außer es kümmern
sich C Funktionen um die Freigabe, dann ist die Ressourcenallokation
allerdings asymetrisch und das SW-Design doof.
Vlad T. schrieb:>> scheiden sich die Geister, ob man den Rueckgabewert von malloc nun>> casten sollte oder nicht. In C++ musst du casten, in C kannst du casten,>> musst du aber nicht.>> in c++ könnte man aber auch direkt `new` benutzen - außer es kümmern> sich C Funktionen um die Freigabe, dann ist die Ressourcenallokation> allerdings asymetrisch und das SW-Design doof.
Beim casten sollte man aber C++ style casts benutzen und raw pointer auf
selbst reservierten space vermeiden (und kein delete).
Kaj schrieb:> Bei> ptr_test = (test*)malloc(sizeof(test));> scheiden sich die Geister, ob man den Rueckgabewert von malloc nun> casten sollte oder nicht. In C++ musst du casten, in C kannst du casten,> musst du aber nicht.
In C ist der Cast vollkommen unnötig.
Wenn man aber vergisst, den nötigen Header einzubinden, nimmt der
Compielr an, dass malloc int zurückgibt. Ohne den Cast kommt dann eine
Warnung. Mit Cast bleibt der Compiler ruhig, da du mit dem Cast sagst,
dass du die Konvertierung so willst. Das ist der Grund, warum die
meisten dazu raten, den Cast nicht hinzuschreiben - er kann einen Fehler
verstecken.
Vlad T. schrieb:> in c++ könnte man aber auch direkt `new` benutzen - außer es kümmern> sich C Funktionen um die Freigabe, dann ist die Ressourcenallokation> allerdings asymetrisch und das SW-Design doof.
Das Design ist dann einfach kaputt und gehört repariert.
Kaj schrieb:> Jo schrieb:>> so wie hier gezeigt mit malloc korrekt?> Du musst noch pruefen, ob du auch speicher bekommen hast.>
1
>ptr_test=(test*)malloc(sizeof(test));
2
>
3
>if(ptr_test==NULL){
4
>/* es konnte kein Speicher reserviert werden */
5
>/* was machst du, wenn du keinen Speicher */
6
>/* bekommen hast? */
7
>}
8
>
Wenn das nicht gerade irgendwas spezielles sicherheitskritisches ist,
oder was was gigantische Matritzen auf einem Supercomputer
multipliziert, ist das ziemlich sinnlos. Es macht den Code extrem schwer
zu lesen, wenn nach jedem alloc ein if ( !x ) return ist, es ist sehr
sehr schwer das insgesamt so hinzubekommen dass es sich sinnvoll verhält
wenn der Speicher voll ist, und auf Systemen wie Linux kommt von malloc
eh nie 0 zurück selbst wenn es keinen Speicher gibt. Dazu sind deine
Optionen zur Fehlerbehandlung sehr beschränkt in den meisten Programmen,
und ob du dann exit(0) machst oder einfach das null dereferenzierst ist
ziemlich wurscht.
Sven B. schrieb:> und auf Systemen wie Linux kommt von malloc> eh nie 0 zurück selbst wenn es keinen Speicher gibt.
Ich nutze linux und habe dass bereits gesehen. Dass passiert
beispielsweise, wenn man versucht mehr Speicher zu reservieren als ram &
swap verfügbar sind (es gibt jedoch die möglichkeit dieses verhalten
auszuschalten). Wenn der Kernel speicher braucht, und es gibt keinen
mehr, kommt dann der OOM-Killer und schiesst die speicherhungrigste
Anwendung ab. Das kann z.B. passieren, wenn eine Page mit reserviertem
Speicher zum ersten mal genutzt wird, wobei der Kernel erst zu dem
Zeitpunkt versucht den speicher dafür tatsächlich zu reservieren.
Sven B. schrieb:> Wenn das nicht gerade irgendwas spezielles sicherheitskritisches ist,> oder was was gigantische Matritzen auf einem Supercomputer> multipliziert, ist das ziemlich sinnlos. Es macht den Code extrem schwer> zu lesen, wenn nach jedem alloc ein if ( !x ) return ist, es ist sehr> sehr schwer das insgesamt so hinzubekommen dass es sich sinnvoll verhält> wenn der Speicher voll ist,
Sehe ich nicht so. Was ist an dem Code if(ptr == NULL) denn schwer
verständlich? Es ist aus meiner Sicht gar keine Option den Fehler nicht
abzufangen, denn sonst wird je nach OS das Programm irgendwann beim
Zugriff beendet, wo es evt. sehr ungünstig ist.
Je nach Funktionalität die den Speicher brauch, muss man halt
entsprechende Ersatzmaßnahmen einleiten. Evt. ist das malloc nur für ein
optionales Feature gedacht und darf nicht gleich zum kill des ganzen
Programms führen...
Gerade im Embedded-Bereich kann das böse enden!
Daniel A. schrieb:> Ich nutze linux und habe dass bereits gesehen. Dass passiert> beispielsweise, wenn man versucht mehr Speicher zu reservieren als ram &> swap verfügbar sind (es gibt jedoch die möglichkeit dieses verhalten> auszuschalten). Wenn der Kernel speicher braucht, und es gibt keinen> mehr, kommt dann der OOM-Killer und schiesst die speicherhungrigste> Anwendung ab. Das kann z.B. passieren, wenn eine Page mit reserviertem> Speicher zum ersten mal genutzt wird, wobei der Kernel erst zu dem> Zeitpunkt versucht den speicher dafür tatsächlich zu reservieren.
Ja, hast du im Detail natürlich recht, und man kann das overcommit auch
per sysctl ausschalten. Aber wenn einfach nur der Speicher voll ist,
kommt i.d.R. kein null zurück. Das typische "mein Programm reserviert zu
viel Speicher weil Endlosschleife oder Leak"-Problem kriegst du damit
nicht.
> Bloß weil du keine Ahnung hast, heißt es nicht, dass fehlertolerante> Programmierung sinnlos wäre.
Es gibt viele Stellen, an denen defensive Programmierung hilfreich ist,
aber nicht beim Speicher reservieren in der typischen
Userspace-Anwendung. Das macht auch kein Mensch, weil es wie gesagt
alles mit diesen Checks vollrümpelt und die Checks in den meisten
Situationen sowieso nix machen können außer exit.
Ich habe mal hier bei $anwendung mit ~150k SLOC gegreppt, es gibt 2449
memory allocations; wenn ich bei jeder ein if ( !x ) { return } dahinter
baue, habe ich schon 7500 Zeilen Code produziert die das absolute
Minimum sind, um sinnvoll zu reagieren, aber in der Form noch absolut
gar nichts bringen. Im Gegenteil, die produzieren nur noch wirrere
Fehlersituationen wenn eine davon tatsächlich auslöst.
> Sehe ich nicht so. Was ist an dem Code if(ptr == NULL) denn schwer> verständlich?
Der Code ist verständlich, aber es wird wahnsinnig viel davon werden für
sehr wenig Gewinn.
> Es ist aus meiner Sicht gar keine Option den Fehler nicht> abzufangen, denn sonst wird je nach OS das Programm irgendwann beim> Zugriff beendet, wo es evt. sehr ungünstig ist.
Pff, Pech, dann ist es halt weg. Viel mehr kannst du mit deinem Check
auch nicht machen. :D
Meines Erachtens ist das wirklich an der völlig falschen Stelle auf
irgendeine "Sauberkeit" auf dem Papier geachtet und als Tipp gerade für
Anfänger sehr unpassend. Die Software mit der man in der Praxis
konfrontiert wird, stürzt ab, weil man in der "falschen" Reihenfolge auf
zwei Buttons klickt. Da hätte man mal defensiv programmieren sollen,
nicht bei der memory allocation.
Sven B. schrieb:> Aber wenn einfach nur der Speicher voll ist,> kommt i.d.R. kein null zurück. Das typische "mein Programm reserviert zu> viel Speicher weil Endlosschleife oder Leak"-Problem kriegst du damit> nicht.
Folgenden Code hat jedenfalls unter Linux meinen Speicher gefüllt, bis
malloc NULL retournierte:
1
#include<stdlib.h>
2
#include<stdio.h>
3
4
intmain(void){
5
while(1){
6
void*Ptr=malloc(1024);
7
if(Ptr==NULL){
8
printf("failed!\n");
9
break;
10
}
11
}
12
13
return0;
14
}
Sven B. schrieb:>> Es ist aus meiner Sicht gar keine Option den Fehler nicht>> abzufangen, denn sonst wird je nach OS das Programm irgendwann beim>> Zugriff beendet, wo es evt. sehr ungünstig ist.> Pff, Pech, dann ist es halt weg. Viel mehr kannst du mit deinem Check> auch nicht machen. :D
Meine Meinung: Lieber ein definiertes Verhalten mit exit, bei dem vorher
evt. noch irgendwelche Daten gesichert werden können, als NULL zu
dereferenzieren. Hängt halt immer von der Situation ab, welche Aktion
die sinnvollste ist.
Be S. schrieb:> Sven B. schrieb:>> Aber wenn einfach nur der Speicher voll ist,>> kommt i.d.R. kein null zurück. Das typische "mein Programm reserviert zu>> viel Speicher weil Endlosschleife oder Leak"-Problem kriegst du damit>> nicht.>> Folgenden Code hat jedenfalls unter Linux meinen Speicher gefüllt, bis> malloc NULL retournierte:
Bei mir nicht.
1
» ./test
2
fish: “./test” terminated by signal SIGKILL (Forced quit)