"Komfort" bei malloc
-
noobLolo schrieb:
NULL ist doch die einzige möglichkeit einen fehler aus der function raus zu bringen, da ja jeder andere wert einen potentiellen speicher bereich darstellt. und ein aufruf mit 0 stellt ja streng genommen keinen fehler dar.
Nein, aber er ist sinnlos, wie schon auf der ersten Seite erwähnt wurde.
Ich habe zum Spass mal das gemacht:while(1) void *z = malloc(0);
Bei mir läuft der Speicher ganz langsam voll, VS 2005, ca 1.6 GB nach 5 Minuten.
Da offensichtlich free() bei malloc(0) nötig ist, würde ich lieber sicherstellen, dass im Programm kein malloc(0) vorkommt.
-
Z schrieb:
Bei mir läuft der Speicher ganz langsam voll, VS 2005, ca 1.6 GB nach 5 Minuten.
Wenn malloc(0) nicht NULL zurückgibt, muss man das natürlich wieder freigeben. Wenn malloc(0) NULL zurückgibt, schadet free() aber auch nicht. Am besten ruft man also einfach zu jedem malloc free auf (wäre käme denn auch auf die Idee, das nicht zu tun?)
Wie gesagt kann malloc(0) vorkommen, wenn man sich einfach die Sonderbehandlung des Falls einer Größe von 0 spart.
Zum Beispiel: Man ließt irgendwelche Pakete aus einer Datei, wobei vorher jeweils die Paketgröße selber in der Datei steht. D.h. man ließt die Größe, malloct so viel Speicher, füllt ihn mit fread(buffer,size,1,f), und macht dann irgendwas damit, wobei man natürlich nur auf Arrayindizes 0 <= i < size zugreift.
Und wenn dann mal als Größe 0 gelesen wird (was ja vielleicht im Eingabeformat erlaubt ist) und malloc NULL liefert, funktioniert das immer noch völlig problemlos und standardkonform, ohne dass man diesen Fall gesondert behandelt haben muss.
-
Z schrieb:
Da offensichtlich free() bei malloc(0) nötig ist, würde ich lieber sicherstellen, dass im Programm kein malloc(0) vorkommt.
die sache ist, stell dir vor du gibst eine verkettete liste frei, in dieser liste sind per malloc(x) besorgte speicher blöcke abgelegt, die freigabe routine müßte nun immer checken ob auch was zum freigeben da ist, da ja ein free(NULL) auch was ganz schlimmes ist. also ist eigentlich das problem verschoben...
-
namespace invader schrieb:
Wie gesagt kann malloc(0) vorkommen, wenn man sich einfach die Sonderbehandlung des Falls einer Größe von 0 spart.
Das ist wohl Geschmackssache. Ich würde bei Werten aus nicht 100%ig vertrauenswürdiger Quelle immer auf Gültigkeit prüfen:
size_t n = irgendwo_hergeholt(); void *a; if (n > 0 && n <= MAX) a = malloc(n); else a = 0; // oder Fehlerbehandlung
-
namespace invader schrieb:
Wie gesagt kann malloc(0) vorkommen, wenn man sich einfach die Sonderbehandlung des Falls einer Größe von 0 spart.
Das klingt sinnvoll. Passt auch gut zum Standard, der vorschreibt, dass man den Zeiger von malloc(0) in jedem Fall an free() weitergeben darf, weil free(NULL) nichts tut.
noobLolo schrieb:
da ja ein free(NULL) auch was ganz schlimmes ist
Hättest nicht mehr oft umblättern müssen bis:
TC2 7.20.3.1 schrieb:
The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. If ptr is a null pointer, no action occurs.
-
noobLolo schrieb:
Z schrieb:
Da offensichtlich free() bei malloc(0) nötig ist, würde ich lieber sicherstellen, dass im Programm kein malloc(0) vorkommt.
die sache ist, stell dir vor du gibst eine verkettete liste frei, in dieser liste sind per malloc(x) besorgte speicher blöcke abgelegt, die freigabe routine müßte nun immer checken ob auch was zum freigeben da ist, da ja ein free(NULL) auch was ganz schlimmes ist. also ist eigentlich das problem verschoben...
habs gerade nochmal getestet, free(0) geht, hab das iwie mit uninitialisierten pointern vertauscht
void *p; free(p);
=> *boom*
lg lolo
-
Z schrieb:
while(1) void *z = malloc(0);
Bei mir läuft der Speicher ganz langsam voll, VS 2005, ca 1.6 GB nach 5 Minuten.
Könnte mir jemand das erklären wieso das so ist?
Das ist irgendwie interessant auch wenn es blödsinnig aussieht.
-
woooooah schrieb:
Z schrieb:
while(1) void *z = malloc(0);
Bei mir läuft der Speicher ganz langsam voll, VS 2005, ca 1.6 GB nach 5 Minuten.
Könnte mir jemand das erklären wieso das so ist?
Das ist irgendwie interessant auch wenn es blödsinnig aussieht.wieso postest du in einen thread den du nicht gelesen hast?
-
noobLolo schrieb:
wieso postest du in einen thread den du nicht gelesen hast?
Ich hab den thread gelesen aber ich verstehe nicht wieso 0 bytes auch eine größe ist. was wird da angefordert?
-
evtl. hast auch ein problem mit deinem englisch
noobLolo schrieb:
...
schauen wir doch mal wie das in der glibc gemacht wurde;)/* Allocate an N-byte block of memory from the heap. If N is zero, allocate a 1-byte block. */ void * rpl_malloc (size_t n) { if (n == 0) n = 1; return malloc (n); }
...
-
danke nooblolo
hab es aus dem thread nicht rauslesen können!
-
heyhoi schrieb:
Ich hab den thread gelesen aber ich verstehe nicht wieso 0 bytes auch eine größe ist. was wird da angefordert?
Nichts. Was die Gnu libc tut, kannst du getrost ignorieren, ist ja keine Referenz-Implementation. Den Speicher verbraucht in dem Fall grossteils/ausschliesslich der Overhead.
-
Wird malloc() mit der Länge 0 aufgerufen ist vorher etwas schiefgelaufen.
Der Fall sollte normaerweise nicht auftreten bzw es sollte vorher geprüft
und reagiert werden.Kann das OS den Speicher nicht bereitstellen ist es so gut wie immer
sinnfrei, das Programm weiterlaufen zu lassen. Wozu auch ?
Also: exit() und raus.Da der Fall äußerst selten vorkommt (ok, bei mir. Mag bei anderen anders
aussehen) ignoriere ich "Nebeneffekte". Da soll sich das OS drum kümmern.
-
Scheppertreiber schrieb:
Kann das OS den Speicher nicht bereitstellen ist es so gut wie immer
sinnfrei, das Programm weiterlaufen zu lassen. Wozu auch ?
Also: exit() und raus.Na weil es vielleicht möglich sein sollte, dass ein bestimmter Programmteil aus irgendwelchen Gründen wie z.B. auch "nicht genug Speicher" nicht ausgeführt werden kann, ohne dass gleich die ganze Software böse abschmiert. Dann lieber die Rückgabe prüfen und ggf. eine Meldung raushauen, damit der User Bescheid weiß, aber nicht gleich den ganzen Prozess abschießen.
-
_matze schrieb:
Na weil es vielleicht möglich sein sollte, dass ein bestimmter Programmteil aus irgendwelchen Gründen wie z.B. auch "nicht genug Speicher" nicht ausgeführt werden kann, ohne dass gleich die ganze Software böse abschmiert. Dann lieber die Rückgabe prüfen und ggf. eine Meldung raushauen, damit der User Bescheid weiß, aber nicht gleich den ganzen Prozess abschießen.
Ok, das hängt von ... ab. In den meisten Fällen hat es ja einen Grund, Speicher
vom OS anzufordern. Klar sind Fälle denk- und konstruierbar wo das Programm auch
ohne weiterlaufen oder sich kontrolliert beenden kann. Nur, bevor ich mir Daten
schieße, lieber abbrechen und nach der Ursache suchen und diese beheben.
-
Scheppertreiber schrieb:
_matze schrieb:
Na weil es vielleicht möglich sein sollte, dass ein bestimmter Programmteil aus irgendwelchen Gründen wie z.B. auch "nicht genug Speicher" nicht ausgeführt werden kann, ohne dass gleich die ganze Software böse abschmiert. Dann lieber die Rückgabe prüfen und ggf. eine Meldung raushauen, damit der User Bescheid weiß, aber nicht gleich den ganzen Prozess abschießen.
Ok, das hängt von ... ab. In den meisten Fällen hat es ja einen Grund, Speicher
vom OS anzufordern. Klar sind Fälle denk- und konstruierbar wo das Programm auch
ohne weiterlaufen oder sich kontrolliert beenden kann. Nur, bevor ich mir Daten
schieße, lieber abbrechen und nach der Ursache suchen und diese beheben.Daraus lässt sich schliessen, dass Programme, die unbedingt immer laufen müssen, malloc nicht benutzen dürfen.
-
Wieso ?
-
Scheppertreiber schrieb:
Wieso ?
Gamz einfach:
Wenn malloc scheitert, dann kann das Programm nicht vernünftig weiterarbeiten => Ein Programm, das ohne Störungen laufen soll, darf nicht auf malloc angewiesen sein.
-
collam schrieb:
Scheppertreiber schrieb:
Wieso ?
Gamz einfach:
Wenn malloc scheitert, dann kann das Programm nicht vernünftig weiterarbeiten => Ein Programm, das ohne Störungen laufen soll, darf nicht auf malloc angewiesen sein.Blödsinn. Wenn malloc scheitert, kann das auch nur bedeuten, dass ein bestimmter Zweig nicht ausgeführt werden kann. Deswegen die ganze SW abzuschiessen ist natürlich Quatsch, wenn der Benutzer doch weiterhin nutzen aus all den anderen Zweigen ziehen kann. Wenn man beispielsweise einen Editor mit vielen Freiheiten, was Speicherverbrauch angeht, bereitstellt, dann kann es durchaus passieren, dass der Benutzer soviele Felder platziert, bis kein Speicher mehr alloziert werden kann. Dann schlägt malloc fehl, er wird darüber informiert, der Editor läuft aber weiterhin und er kann noch weiterarbeiten (Datei speichern, vielleicht auch Felder löschen usw.).
-
Ich hatte auch mal so ein Phänomen bei einem Parser, der am PC lief und auf einem Controller crashte. Grund war tatsächlich das malloc(0), das sich unterschiedlich verhielt.
Bevor ich mich mit dem "unique" Pointer für die Blocksize 0 abplage, die dann ja wieder nur auf einem Compiler funktionieren würde, habe ich malloc(0) als Fall aussortiert, obwohl logisch kein Fehler dahintersteckte, wenn malloc(0) auf allen Kisten NULL zurückgeliefert hätte. Ist aber in der bösen Realwelt leider nicht so.
Nochwas: Wenn man Pointer immer mit NULL initialisiert und beim free() wieder auf NULL setzt, kann eigentlich nichts schiefgehen und vereinfacht den cleanup.
collam schrieb:
Wenn malloc scheitert, dann kann das Programm nicht vernünftig weiterarbeiten => Ein Programm, das ohne Störungen laufen soll, darf nicht auf malloc angewiesen sein.
Bullshit. Wenn malloc() fehlschlägt, heißt das, daß kein Speicher mehr frei ist, nicht mehr und nicht weniger. Bei obig erwähntem Parser gibt's den Fall auf dem Controller mehrfach und bedeutet nur, daß ich die Befehlsketten, die im Speicher schon bearbeitet sind, auf die SD- Karte weggeschrieben und gefreed werden sollen. Das ist keine Störung.