Die Leute haben bereits darauf hingewiesen, dass Sie sich wahrscheinlich keine Gedanken über die Speicherfreigabe machen müssen, wenn Sie Ihren Code im Fehlerfall nur beenden (oder abbrechen). Aber nur für den Fall, hier ist ein Muster, das ich entwickelt habe und viel nutze, um im Fehlerfall Ressourcen zu erstellen und abzubauen.Hinweis: Ich zeige hier ein Muster, um einen Punkt zu machen, nicht um echten Code zu schreiben!
int foo_create(foo_t *foo_out) {
int res;
foo_t foo;
bar_t bar;
baz_t baz;
res = bar_create(&bar);
if (res != 0)
goto fail_bar;
res = baz_create(&baz);
if (res != 0)
goto fail_baz;
foo = malloc(sizeof(foo_s));
if (foo == NULL)
goto fail_alloc;
foo->bar = bar;
foo->baz = baz;
etc. etc. you get the idea
*foo_out = foo;
return 0; /* meaning OK */
/* tear down stuff */
fail_alloc:
baz_destroy(baz);
fail_baz:
bar_destroy(bar);
fail_bar:
return res; /* propagate error code */
}
Ich kann wetten, dass ich einige Kommentare bekommen werde, die sagen, "das ist schlecht, weil Sie goto verwenden". Aber dies ist eine disziplinierte und strukturierte Verwendung von goto, die den Code klarer, einfacher und einfacher zu verwalten macht, wenn er konsequent angewendet wird. Sie können keinen einfachen, dokumentierten Abbauweg durch den Code ohne ihn erreichen.
Wenn Sie dies in realen kommerziellen Code sehen möchten, werfen Sie einen Blick auf, sagen wir arena.c from the MPS (was zufällig ein Speicher-Management-System ist).
Es ist eine Art von armer-Mann-Versuch ... Fertig-Handler, und gibt Ihnen etwas ein bisschen wie Destruktoren.
Ich werde jetzt wie ein Greybeard klingen, aber in meinen vielen Jahren der Arbeit am C-Code anderer Leute ist das Fehlen klarer Fehlerpfade oft ein sehr ernstes Problem, besonders im Netzwerkcode und anderen unzuverlässigen Situationen. Die Einführung von ihnen hat mich gelegentlich zu einem beträchtlichen Beratungseinkommen geführt.
Es gibt viele andere Dinge zu Ihrer Frage zu sagen - ich werde es nur mit diesem Muster verlassen, falls das nützlich ist.
Sie könnten sogar die Funktion atexit() verwenden und eine Funktion schreiben, um den gesamten auf der verknüpften Liste zugewiesenen Speicher (der in diesem Fall eine globale Variable sein müsste) nach einem einfachen Aufruf von exit() freizugeben - so würden Sie es tun Ich darf nicht vergessen, keinen einfachen Ausgang zu verwenden(). –
Aber warum? Das Betriebssystem führt bereits eine Liste des zugewiesenen Speichers. Duplizierst du diese Funktionalität, bremst du den Shut-Down-Prozess einfach ab ohne irgendeinen Nutzen außer ein bisschen Ego-Inflation. Wenn Sie nicht beabsichtigen, Ihre Anwendung auf MSDOS zu portieren, lassen Sie das Betriebssystem seine Aufgabe erfüllen. – Eclipse
Das Warum ist, weil schließlich die Disziplin und die Funktionalität Ihnen helfen, Speicherlecks aufzuspüren. Wenn Sie es richtig codieren, kann es über eine DEFINE- oder MACRO-Definition ausgeschaltet werden. – ojblass