Fehlerbehandlung bei malloc

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Fehlerbehandlung bei malloc
Hallo,
muss man den Fall beachten, dass, wenn malloc keinen freien Speicher findet, entsprechend agiert (z. B. -1 zurückgibt). Beispiel:

ele = malloc(sizeof(struct node));
if (ele == NULL) return -1;

LG Gabriel


Ja.


Ok, danke!


Wichtig ist auch, dass im Fehlerfall aller schon angeforderter Speicher wieder freigeben wird.

int foo(int a) {
    char *x = malloc(42);
    if (x == NULL) {
        return -1;
    }

     if (a < 0) {
          free(x); // <-- dieses free ist wichtig, sonst "verliert" man Speicher wenn a < 0 ist
          return -1;
     }

    // ...
}

In diesem Beispiel könnte man natürlich einfach das [m]if[/m] nach vorne ziehen, aber das geht nicht immer.

1 „Gefällt mir“

Gibt es da eigentlich noch eine elegantere Lösung, als für jeden exit einzeln das bisher allocierte hinzuschreiben und ohne sich eine eigene Memoryverwaltung zu schreiben, die sich alle allocierten Pointer merkt?


goto


Hm, stimmt. Da hat man dann nur eine Zeile und muss nicht Tonnen an Argumenten als Parameter an eine Funktion übergeben.


MACROS, MACROS, MACROS!



Das nennt sich höhere Programmiersprache! :slight_smile: Z. B. C++.

1 „Gefällt mir“

Macros klingen interessant.

Wobei ich mich frage, wie genau man das bewerkstelligen will?

Höhere Programmiersprache sind selbstverständlich eine Option, nur dürfen wir die in SysProg leider nicht verwenden.


[quote=Destranix]
Macros klingen interessant.[/quote]
Devil’s advocate: Makros klingen ungetypt und fehleranfällig.

Aber man kann sich in SP ja ruhig mal austoben damit :smiley: Bitte nur keine production-level Software damit schreiben :wink:


Also wirklich viel kann man doch nicht falsch machen, wenn man jetzt Makros nur für Preprozessorzeugs nutzt und nur dort, wo es tatsächlich Sinn macht, oder?


Mit Konsistenz und Quality Assurance kann man selbst in der fehleranfälligsten Programmiersprache funktionierende Software schreiben. Selbst die trivialsten Makros sind nicht trivial zu implementieren. Versuch z. B. die Maximumsfunktion zu implementieren – ohne doppelte Auswertung des Arguments! Denn die könnte seiteneffektbehaftet sein!


Eine Maximum-Präprozessoranweisung wäre eher etwas, was ich vom Compiler erwarten würde, dass er automatisch macht.

Ich würde mich bei so Makros nur auf ifdef-Zeug und direktes ersetzen von konstanten Werten beschränken, wobei letzteres auch nur dann erfolgen sollte, wenn man das nicht durch Konstanten realisieren kann.


Kommt auf die genaue Anwendung an. Ich finde (trotz den berechtigten und richtigen Einwänden von Marcel[Inf]) zeug wie dieses immer wieder lustig:

#define withmem(type, var) for (void *var = malloc(sizeof(type)); var; free(var), var = NULL)

wo man dann Zeug macht wie

withmem(struct z, x) {
   /* arbeite mit x */
}

um „innerhalb von einem block“ Speicher benutzen kann (kann für bessere Fehlerbehandlung erweitert werden.

Ich hab für SP2 ein ganzen macroset entwickelt für Fehlerbehandlungen, wo ich dann code schrieb wie

MUSTA(RN, var1, malloc, 2);
/* weist var1 allozierten speicher zu, generiert durch malloc(2), und verlässt die Funktion mit -1 andernfalls */

MUSTD(WC, struct xzy, var2, malloc, 32); 
/* deklariert Variable var2 vom Typ struct xzy, analog zum vorherigem Beispiel und gibt Fehlermeldung + continue't bei einem Fehler */

Ich würde einem nicht empfehlen dieses zu nutzen, da einerseits ich das im Nachhinein anders gestaltet hätte, und da man leicht viele Fehler machen kann (was ich auch gemacht hab ^^). Wenn schon, würde die interessante Lektion sein macros als Möglichkeit anzusehen eine Sprache zu „erweitern“, als ein umständliches Alias-System.