"Komfort" bei malloc
-
Gut, das ist das C-Forum, hab ich nicht bedacht (deine niveaulosen Beleidigungen kannst du dir natürlich trotzdem sparen). Für den Fall, dass der MS-Compiler verwendet wird, gibt es allerdings immerhin die Exception-Erweiterung für C (__try, __except, __finally).
-
_matze schrieb:
Gut, das ist das C-Forum, hab ich nicht bedacht (deine niveaulosen Beleidigungen kannst du dir natürlich trotzdem sparen). Für den Fall, dass der MS-Compiler verwendet wird, gibt es allerdings immerhin die Exception-Erweiterung für C (__try, __except, __finally).
__try, __except und __finally haben haben rein garnichts mit der Frage von plizz zu tun. Warum schreibst du hier wenn du keine Ahnung hast?
-
Ganz ruhig. Mir ist zwar durchaus bewusst, dass die Frage nach der richtigen malloc-Lösung enormes Konfliktpotenzial in sich trägt, ich wollte aber dennoch keinen Privatkrieg damit auslösen.
Zum obigen Code: Im Endeffekt läuft es da wohl auf die Benutzung von exit() hinaus, was das Programm scheinbar schließt. Das riecht allerdings nach einer Lösung, bei der das halbe Forum hier wild schreiend die Fackel anzünden würde, da es wohl irgendwelche Nebenwirkungen gibt a la "vorher allokierter Speicher wird nicht freigegeben". Oder ist diese exit-Variante eher unproblematisch und man kann sie guten Gewissens verwenden?
-
Du kannst mit ruhiger Gewissheit davon ausgehen, dass diese Vorgehensweise Grütze ist.
MfG,
B.B.
-
plizzz schrieb:
Oder ist diese exit-Variante eher unproblematisch und man kann sie guten Gewissens verwenden?
Windows gibt allen Speicher frei wenn das Programm beendet wird.
-
collam schrieb:
plizzz schrieb:
Oder ist diese exit-Variante eher unproblematisch und man kann sie guten Gewissens verwenden?
Windows gibt allen Speicher frei wenn das Programm beendet wird.
Von Windows war hier übrigens nie die Rede. Willst du dich wirklich darauf verlassen, dass jedes in Frage kommende Betriebssystem unter allen Umständen alle Speicherleichen eines beendeten Prozesses freimacht? Das ist einfach schlechter Stil. Wer Speicher anfordert, sollte diesen auch wieder freigeben. Zumal eine Rückgabe NULL von malloc nicht unbedingt bedeuten muss, dass man sein Programm komplett beenden will (auch, wenn plizzz es in diesem Fall so machen will; vielleicht entscheidet er später auch mal anders)...
-
collam schrieb:
void *m = malloc (length);
if (m == 0)Besser ist stattdessen
if (!m && length)
, da malloc ja NULL zurückgeben kann, wenn man ein Array der Länge 0 haben will._matze schrieb:
Gut, das ist das C-Forum, hab ich nicht bedacht (deine niveaulosen Beleidigungen kannst du dir natürlich trotzdem sparen). Für den Fall, dass der MS-Compiler verwendet wird, gibt es allerdings immerhin die Exception-Erweiterung für C (__try, __except, __finally).
Man kann sich auch mit longjmp und Makros Exceptions basteln. Natürlich muss man dann auch das ganze Programm entsprechend umschreiben, also mit Verwaltung eines Cleanup-Stacks usw. Ich würde damit aber nicht anfangen, allein um malloc-Fehlschläge abzufangen, die in der Praxis vermutlich ohnehin niemals auftreten.
plizzz schrieb:
da es wohl irgendwelche Nebenwirkungen gibt a la "vorher allokierter Speicher wird nicht freigegeben".
Der Standard garantiert nicht, dass es solche Nebenwirkungen nicht gibt, aber in der Regel kann man trotzdem davon ausgehen, dass es keine Probleme gibt.
Es gibt sinnvollere Dinge, die man machen kann, als sein Programm von Malloc-Fehlerbehandlung aufzublähen.
-
namespace invader schrieb:
allein um malloc-Fehlschläge abzufangen, die in der Praxis vermutlich ohnehin niemals auftreten.
Das kommt halt auf das Programm an. Bei uns gibt es solche Fälle (wir hantieren aber auch mit sehr großen Speicherblöcken). Das kleine Prgrämmchen, das in Summe 20 MB braucht, wird malloc-Fehler wohl kaum zu Gesicht bekommen.
-
namespace invader schrieb:
Besser ist stattdessen
if (!m && length)
, da malloc ja NULL zurückgeben kann, wenn man ein Array der Länge 0 haben will.Was man auch als Fehler ansehen könnte.
-
_matze schrieb:
Das kommt halt auf das Programm an. Bei uns gibt es solche Fälle (wir hantieren aber auch mit sehr großen Speicherblöcken). Das kleine Prgrämmchen, das in Summe 20 MB braucht, wird malloc-Fehler wohl kaum zu Gesicht bekommen.
Ok, kommt eben darauf an: Wenn man sehr große Blöcke reservieren will, deren Größe vielleicht auch von den Eingabedaten abhängt, ist es sicher sinnvoll, vernünftig auf den Fehler zu reagieren.
Wenn es nur um ein paar 20-Byte-Objekte geht, und man unabhängig von den Eingabedaten sicherstellen kann, wie viele es höchstens werden, ist es durchaus legitim, davon auszugehen, dass ein malloc-Fehlschlag entweder ein Problem beim Betriebssystem ist oder ein Bug im eigenen Programm ist. Und dafür eine komplizierte Fehlerbehandlung zu schreiben halte ich für übertrieben. Letztendlich ist das verglichbar mit einem Stacküberlauf, bei dem ja auch das Programm einfach beendet wird, ohne dass noch irgendwas freigegeben wird.
-
collam schrieb:
Was man auch als Fehler ansehen könnte.
Nicht unbedingt, manchmal läuft es eben darauf hinaus, dass man von irgendetwas nur 0 Elemente hat, und NULL ist ein problemlos verwendbarer Zeiger auf ein Array der Länge 0, man kann dann in einer for-Schleife alle 0 Elemente durchlaufen usw., und das Array später auch mit realloc vergrößern.
-
namespace invader schrieb:
Ok, kommt eben darauf an: Wenn man sehr große Blöcke reservieren will, deren Größe vielleicht auch von den Eingabedaten abhängt, ist es sicher sinnvoll, vernünftig auf den Fehler zu reagieren.
Wenn es nur um ein paar 20-Byte-Objekte geht, und man unabhängig von den Eingabedaten sicherstellen kann, wie viele es höchstens werden, ist es durchaus legitim, davon auszugehen, dass ein malloc-Fehlschlag entweder ein Problem beim Betriebssystem ist oder ein Bug im eigenen Programm ist. Und dafür eine komplizierte Fehlerbehandlung zu schreiben halte ich für übertrieben. Letztendlich ist das verglichbar mit einem Stacküberlauf, bei dem ja auch das Programm einfach beendet wird, ohne dass noch irgendwas freigegeben wird.
Full Ack, finde ich ok so (auch, wenn bei uns sogar für kleine 50-Byte-Allokationen die malloc-Rückgabe geprüft wird...).
-
Ich habe es jetzt doch so gelöst, dass ich bei fehlgeschlagenem malloc NULL oder 0 bis in die main zurückgebe und dann halt eben da beende. Mir ist ein fehlgeschlagener malloc zwar auch noch nie untergekommen und ich weiß auch nicht, ob das je passieren wird, allerdings ist bei mir der zu allokierende Speicher eben von den Eingabedaten abhängig und da mache ich dann lieber so eine Abfrage rein. Aber eine "einfache", unumstrittene Lösung scheint es da ja gar nicht so wirklich zu geben.
-
namespace invader schrieb:
collam schrieb:
Was man auch als Fehler ansehen könnte.
Nicht unbedingt, manchmal läuft es eben darauf hinaus, dass man von irgendetwas nur 0 Elemente hat, und NULL ist ein problemlos verwendbarer Zeiger auf ein Array der Länge 0, man kann dann in einer for-Schleife alle 0 Elemente durchlaufen usw., und das Array später auch mit realloc vergrößern.
Der Rückgabewert von malloc ist unbrauchbar, wenn ich malloc mit 0 aufrufe. Warum sollte man es dann tun?
-
plizzz schrieb:
Ich habe es jetzt doch so gelöst, dass ich bei fehlgeschlagenem malloc NULL oder 0 bis in die main zurückgebe und dann halt eben da beende.
Wenn du die Null nicht als Fehlermeldung verwenden kannst, könntest du auch einen weiteren Paramter einführen, einen Zeiger auf eine Variable, in der die Fehlermeldung abgelegt wird. Oder eine globale Variable (globale Variablen sind aber nicht immer eine gute Idee).
plizzz schrieb:
Mir ist ein fehlgeschlagener malloc zwar auch noch nie untergekommen und ich weiß auch nicht, ob das je passieren wird, allerdings ist bei mir der zu allokierende Speicher eben von den Eingabedaten abhängig und da mache ich dann lieber so eine Abfrage rein.
Du kannst einfach nicht wissen, welche Umstände du vorfinden wirst. Vielleicht ist die Ziel-CPU gerade mit der Suche nach einem 17er-Sudoku beschäftigt und hat dafür gerade den ganzen Speicher in Beschlag genommen. Soll schon passiert sein.
plizzz schrieb:
Aber eine "einfache", unumstrittene Lösung scheint es da ja gar nicht so wirklich zu geben.
Zumindest hat sie noch keiner entdeckt. Davon auszugehen, dass malloc() schon nicht NULL liefern wird, ist jedenfalls keine. Wenn du dich andererseits darauf verlassen willst, dass das Betriebssystem irgendwelche Nicht-Standard-Magie macht, bist du im falschen Forum.
Vielleicht kommt ein Garbage Collector deiner Vorstellung von Komfort entgegen:
http://www.hpl.hp.com/personal/Hans_Boehm/gc/Vielleicht ist C auch einfach nicht das passende Werkzeug für deine Aufgabe, üblicherweise ist man in C froh über die manuelle Speicherverwaltung.
-
Nein nein, da verstehst du mich falsch. Ich möchte im Grunde nichts verändern an meiner Speicherverwaltung. Ich wollte lediglich wissen, ob es nicht evtl. eine übersichtlichere Methode gibt, die ganzen malloc-Abfragen zu realisieren, anstatt irgendwelche Rückgabewerte durch die Funktionen durchzureichen. Da es da scheinbar keine eierlegende Wollmilchsau in dieser Angelegenheit gibt, bleibe ich bei dieser Methode und versuche halt, diese sinnvoll einzubinden. Bloß will man es ja doch schon besser machen, wenn es denn besser geht.
-
collam schrieb:
Der Rückgabewert von malloc ist unbrauchbar, wenn ich malloc mit 0 aufrufe. Warum sollte man es dann tun?
Weil es manchmal eleganter ist, als den Fall einer Größe von 0 gesondert behandeln zu müssen. Manchmal hat man eben Datenpakete oder sonstwas der Länge 0, die aber trotzdem nicht komplett unterschlagen werden dürfen.
-
plizzz schrieb:
Ich habe es jetzt doch so gelöst, dass ich bei fehlgeschlagenem malloc NULL oder 0 bis in die main zurückgebe und dann halt eben da beende.
Genau so ist es fein.
plizzz schrieb:
Aber eine "einfache", unumstrittene Lösung scheint es da ja gar nicht so wirklich zu geben.
Doch gibt es. Z.B. aus der main heraus die Funktionen für die Speicherfreigabe aufrufen und mit 'return irgendwas' beenden.
-
namespace invader schrieb:
Manchmal hat man eben Datenpakete oder sonstwas der Länge 0, die aber trotzdem nicht komplett unterschlagen werden dürfen.
Das ist doch Unsinn! Alles was die Länge 0 hat kann unterschlagen werden.
-
namespace invader schrieb:
collam schrieb:
void *m = malloc (length);
if (m == 0)Besser ist stattdessen
if (!m && length)
, da malloc ja NULL zurückgeben kann, wenn man ein Array der Länge 0 haben will.schweres thema, was sagt der standard dazu?
7.20.3 Memory management functions schrieb:
If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementationdefined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
so wie ich das verstehe, kann das jeder so machen wie er will! hat mich also nicht weiter gebracht...
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); }
huch was ist denn das, ein malloc(0) reserviert auch ein char
macht ja auch sinn, denn das ist mehr oder weniger die einzige möglichkeit das relativ sauber über die bühne zu bringen.noch ein kurzer test
#include <stdio.h> #include <stdlib.h> int main() { void *x = malloc(0); if(x==NULL) puts("error"); else puts("no error"); return 0; } ausgabe: "no error"
lg lolo