Warum den Rückgabewert von free auf void umwandeln?

Lesezeit: 7 Minuten

Benutzeravatar von Adam Johnston
Adam Johnston

Ich lese ein Buch (Programmierung mit POSIX-Threads von Butenhof, 1997), das C verwendet, und ich bin auf die folgende Zeile gestoßen:

(void)free(data);

Hier, data ist nur ein Zeiger auf eine zugewiesene Struktur,

data = malloc(sizeof(my_struct_t));

Warum ist das Ergebnis von free geworfen zu werden void?

Nach meinem Verständnis von C scheint dies aus zwei Gründen keinen Sinn zu machen:

  • Die kostenlose Funktion kehrt bereits zurück void
  • Der Code verwendet den Rückgabewert nicht (er wird nicht einmal einer Variablen zugewiesen)

Das Buch wurde 1997 geschrieben. Ist das eine Art Vermächtnis?

Der Autor erwähnt, dass die Beispiele auf Digital Unix 4.0d ausgeführt wurden, aber ich kann mir immer noch keinen Grund vorstellen, jemals das Ergebnis einer Funktion umzuwandeln, wenn Sie dieses Ergebnis nicht verwenden werden.

  • Einige mögliche Erklärungen finden Sie hier: stackoverflow.com/questions/689677/…

    – Timo

    10. März 2020 um 21:07 Uhr

  • Aus Neugier, wann ist Ihr C-Buch erschienen? (Welches Buch ist es?) Wenn es vor etwa 1995 ist, könnte es eine Rechtfertigung dafür geben – Standard-C-Compiler waren davor nicht allgegenwärtig. Wenn es danach veröffentlicht wird und immer noch die Besetzung enthält (und keine Erklärung dafür, warum), machen Sie sich Sorgen darüber, welche anderen schlechten Angewohnheiten es Ihnen beibringt. Holen Sie sich ein neueres Buch!

    – Jonathan Leffler

    10. März 2020 um 21:32 Uhr


  • Sieht aus wie Programmierung mit POSIX-Threads

    – Eugen Sch.

    10. März 2020 um 21:37 Uhr


  • @JonathanLeffler Wie in meinem ursprünglichen Beitrag erwähnt, wurde das Buch 1997 veröffentlicht und verwendete UNIX 4.0d. Das Buch ist “Programming with POSIX Threads” von David R. Butenhof. Bisher war es sehr informativ und wurde von einem der ursprünglichen Mitwirkenden am POSIX-Thread-Standard geschrieben.

    – Adam Johnston

    10. März 2020 um 21:38 Uhr

  • Ich habe meine Kopie davon in der letzten Woche benutzt – ja, es ist immer noch nützlich. Es wurde an der Schwelle zum „allgegenwärtigen Standard C“ geschrieben (ich sagte „ungefähr 1995“). Das „UNIX 4.0d“ klingt nach Digital UNIX – dort hat Butenhof gearbeitet, und das Vorwort erwähnt es. Behandle den Gips free() als eine Kuriosität im Buch, die Sie nicht nachahmen müssen. Es war vor langer Zeit einmal halb relevant, aber es ist nicht mehr relevant.

    – Jonathan Leffler

    10. März 2020 um 21:43 Uhr


Benutzeravatar von Eugene Sh
Eugen Sch.

Wenn wir über den Standard sprechen free Funktion dann sein Prototyp ist

void free(void *ptr);

Daher ist die Besetzung völlig unbrauchbar.
Nun einige Spekulationen.

Der Autor hat möglicherweise vergessen, die stdlib.h Header, der diesen Prototyp deklariert, sodass der Compiler den Rückgabetyp davon als annimmt int. Während der statischen Analyse dieses Codes warnte der Compiler nun vor dem unbenutzten Rückgabewert dessen, was er für einen nicht-void Funktion. Solche Warnungen werden normalerweise durch Hinzufügen des Casts zum Schweigen gebracht void.

  • Beachten Sie jedoch, dass, wenn die Besetzung aus dem spekulierten Grund eingeführt wurde, sie verwendet wird, um die Warnung zum Schweigen zu bringen falsch. Der Compiler weist in diesem Fall einen anderen Typ zu free als es tatsächlich der Fall ist, mit dem Ergebnis, dass der Aufruf ein undefiniertes Verhalten aufweist (unter der Annahme der C90-Semantik, bei der der Aufruf einer nicht deklarierten Funktion nicht in allen Fällen von Natur aus UB aufweist). In der Praxis ist es plausibel, dass dies dazu führen würde Bona Fide Fehlverhalten auf einigen Systemen. Die richtige Lösung besteht darin, eine korrekte Deklaration für die Funktion bereitzustellen.

    – Johannes Bollinger

    10. März 2020 um 21:56 Uhr


  • Insbesondere fehlen in den Beispielen in “Programmieren mit POSIX-Threads” immer wieder die entsprechenden Standard-Header. Vielleicht war dies eine schlechte Praxis des Autors, sie hätten ein nicht standardmäßiges Compiler-Setup verwenden können, das standardmäßig alle Standardbibliotheken enthielt.

    – Ludin

    11. März 2020 um 11:58 Uhr


Es wäre ein Vermächtnis Sache!

Bevor es eine C-Norm gab, die free() Funktion wäre (implizit) vom Typ gewesen int — weil es noch keinen zuverlässigen Typ gab void damit es zurückkommt. Es wurde kein Wert zurückgegeben.

Als der Code zum ersten Mal modifiziert wurde, um mit Standard-C-Compilern zu arbeiten, enthielt er wahrscheinlich nicht <stdlib.h> (weil es vor dem Standard nicht existierte). Alter Code würde schreiben extern char *malloc(); (vielleicht ohne die extern) für die Allokationsfunktionen (ähnlich für calloc() und realloc()) und musste nicht deklariert werden free(). Und der Code würde dann den Rückgabewert in den richtigen Typ umwandeln – denn das war zumindest auf einigen Systemen notwendig (einschließlich dem, auf dem ich C gelernt habe).

Irgendwann später die (void) cast wurde hinzugefügt, um dem Compiler (oder wahrscheinlicher lint), dass “der Rückgabewert von free() wird absichtlich ignoriert”, um eine Beschwerde zu vermeiden. Aber es wäre besser gewesen, hinzuzufügen <stdlib.h> und lassen Sie seine Erklärung extern void free(void *vp); erzählen lint oder der Compiler, dass es keinen zu ignorierenden Wert gab.

JFTR: Mitte der 80er Jahre war der ICL Perq ursprünglich auf eine wortorientierte Architektur ausgerichtet und das char * Die Adresse für einen Speicherort war eine ganz andere Nummer als der ‘anything_else-Zeiger’ auf denselben Ort. Es war entscheidend zu erklären char *malloc() irgendwie; Es war entscheidend, das Ergebnis davon in einen anderen Zeigertyp umzuwandeln. Die Besetzung hat tatsächlich die von der CPU verwendete Nummer geändert. (Viel Jubel gab es auch, als der Hauptspeicher auf unseren Systemen von 1 MiB auf 2 MiB aufgerüstet wurde – da der Kernel etwa 3/4 MiB verbrauchte, bedeutete dies, dass Benutzerprogramme 1 1/4 MiB vor dem Paging verwenden konnten usw.)

  • Ich habe gerade eine Kopie von K&R, 1. Ausgabe, geöffnet, die eine Implementierung von enthält free() auf P. 177, die implizit zurückkehrt int.

    – ad absurdum

    10. März 2020 um 21:24 Uhr


  • Na sicher – void wurde zu einigen Systemen (vielleicht Unix System III) hinzugefügt, bevor der Standard veröffentlicht wurde, aber das war kein Teil von C, als K&R 1st Edn geschrieben wurde (1978). Eine Funktion, die keinen Wert zurückgab, wurde ohne Rückgabetyp deklariert (was bedeutete, dass sie zurückgegeben wurde int), und solange Sie den nicht zurückgegebenen Wert nicht verwendet haben, gab es kein Problem. Der C90-Standard musste diese Art von Code als gültig behandeln – er wäre als Standard kläglich gescheitert, wenn dies nicht der Fall gewesen wäre. Aber C99 entfernte das ‘implizit int‘ und ‘implizite Funktionsdeklaration’ Regeln. Nicht der ganze Code der Welt hat aufgeholt.

    – Jonathan Leffler

    10. März 2020 um 21:27 Uhr


  • Op behauptet, das Buch sei 1997 geschrieben worden. Worüber Sie hier sprechen, ist ein sehr früher Pre-Standard „K&R C“, und es scheint unwahrscheinlich, dass irgendjemand überhaupt ein Buch darüber schreiben würde. Das einzige derartige Buch, das meines Wissens existierte, war tatsächlich K&R 1. Auflage.

    – Ludin

    11. März 2020 um 11:45 Uhr


  • Es war eine häufige (wenn auch weltfremde) Praxis, Header nicht einzufügen, wenn man dachte, man könne mit impliziter Deklaration davonkommen, weil die Leute dachten, dies würde die Bauzeit verkürzen.

    – Spencer

    11. März 2020 um 13:16 Uhr

  • Benutzt jemand a (void) Besetzung für printf()??

    – Luis Colorado

    11. März 2020 um 19:17 Uhr

Benutzeravatar von SS Anne
SS Anne

Diese Besetzung wird nicht benötigt. Zu der Zeit wäre es wahrscheinlich nicht so gewesen, da C in Form von C89 standardisiert worden war.

Wenn es gewesen wäre, wäre es daran gelegen implizite Deklaration. Dies bedeutete normalerweise, dass die Person, die den Code schrieb, dies vergessen hatte #include <stdlib.h> und ein statischer Analysator wurde verwendet. Dies ist nicht die beste Problemumgehung und eine viel bessere Idee wäre gewesen, einfach #include <stdlib.h> stattdessen. Hier sind einige Formulierungen von C89 über die implizite Deklaration:

Besteht der Ausdruck, der bei einem Funktionsaufruf der eingeklammerten Argumentliste vorangeht, ausschließlich aus einem Bezeichner und ist für diesen Bezeichner keine Deklaration sichtbar, so wird der Bezeichner implizit genau so deklariert, als ob im innersten Block, der den Funktionsaufruf enthält, die Deklaration erfolgt

extern int identifier();

erschien.

Aber das ist seltsam, weil sie das Ergebnis nicht werfen malloc entweder und malloc und free befinden sich in derselben Header-Datei.

Es ist auch möglich, dass dies nur ein Fehler ist oder eine Möglichkeit, dem Leser dies mitzuteilen free gibt kein Ergebnis zurück.

  • Nur weil eine Sprache standardisiert wird, bedeutet das nicht, dass jeder sofort seine Toolchain und seinen Code aktualisiert, um dieser zu entsprechen. Es ist plausibel, dass „K&R“ C im alten Stil weitere 8 Jahre geblieben ist. Dennoch stimme ich zu, dass es seltsam ist, dass ein statisches Analysetool eine Besetzung erfordert free aber nicht für malloc.

    – dan04

    11. März 2020 um 17:00 Uhr

  • @dan04 Sie verwenden normalerweise das Ergebnis von malloc 😉 Ich bin kein Fan davon, Dinge wie (void) printf (…) zu schreiben, um den Compiler davon abzuhalten, Warnungen auszuspucken, aber “muss ohne Warnungen kompilieren, auch die dummen” ist etwas, das passiert in vielen Projekten.

    – richardb

    11. März 2020 um 20:49 Uhr

1419150cookie-checkWarum den Rückgabewert von free auf void umwandeln?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy