Ich lese ein Buch ( Programmieren mit POSIX-Threads von Butenhof, 1997), das C verwendet, und 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 der free
Besetzung void
?
Nach meinem Verständnis von C scheint dies aus zwei Gründen keinen Sinn zu ergeben:
- Die freie Funktion kehrt bereits zurück
void
- Der Code verwendet nicht den Rückgabewert (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 unter Digital Unix 4.0d ausgeführt wurden, aber ich kann mir immer noch keinen Grund vorstellen, das Ergebnis einer Funktion jemals umzuwandeln, wenn Sie dieses Ergebnis nicht verwenden.
free()
als eine Kuriosität in dem Buch, die Sie nicht emulieren müssen. Es war vor langer Zeit halb relevant, aber es ist nicht mehr relevant.Antworten:
Wenn wir über die Standardfunktion sprechen,
free
dann ist ihr PrototypDaher ist die Besetzung völlig nutzlos.
Nun einige Spekulationen.
Der Autor hat möglicherweise vergessen, den
stdlib.h
Header einzuschließen, der diesen Prototyp deklariert, sodass der Compiler den Rückgabetyp als annimmtint
. Während der statischen Analyse dieses Codes warnte der Compiler nun vor dem nicht verwendeten Rückgabewert dessen, was er für eine Nichtfunktion hältvoid
. Solche Warnungen werden normalerweise durch Hinzufügen der Besetzung zu zum Schweigen gebrachtvoid
.quelle
free
als tatsächlich, mit dem Ergebnis, dass der Aufruf ein undefiniertes Verhalten aufweist (vorausgesetzt, die C90-Semantik, bei der das Aufrufen einer nicht deklarierten Funktion nicht in allen Fällen von Natur aus UB aufweist). In der Praxis ist es plausibel, dass dies auf einigen Systemen zu einem echten Fehlverhalten führen würde. Die richtige Lösung besteht darin, eine korrekte Deklaration für die Funktion bereitzustellen.Es wäre eine Legacy-Sache!
Bevor es einen C-Standard gab, wäre die
free()
Funktion (implizit) vom Typ gewesenint
- da es noch keinen verlässlichen Typvoid
für die Rückgabe gab. Es wurde kein Wert zurückgegeben.Als der Code zum ersten Mal für die Verwendung mit Standard-C-Compilern geändert wurde, war er wahrscheinlich nicht enthalten
<stdlib.h>
(da er vor dem Standard nicht vorhanden war). Alter Code würdeextern char *malloc();
(möglicherweise ohneextern
) für die Zuordnungsfunktionen schreiben ( ähnlich fürcalloc()
undrealloc()
) und musste nicht deklariert werdenfree()
. Und der Code würde dann den Rückgabewert auf den richtigen Typ umwandeln - da dies zumindest auf einigen Systemen erforderlich war (einschließlich dem, auf dem ich C gelernt habe).Einige Zeit später wurde die
(void)
Besetzung hinzugefügt, um dem Compiler (oder wahrscheinlicherlint
) mitzuteilen, dass "der Rückgabewert vonfree()
absichtlich ignoriert wird", um eine Beschwerde zu vermeiden. Es wäre jedoch besser gewesen, die<stdlib.h>
Deklaration hinzuzufügen und dem Compilerextern void free(void *vp);
mitzuteilen,lint
dass kein Wert zu ignorieren ist.JFTR: Mitte der 80er Jahre befand sich der ICL Perq ursprünglich in einer wortorientierten Architektur, und die
char *
Adresse für einen Speicherort war eine ganz andere Zahl als der Zeiger "any_else" auf denselben Speicherort. Es war entscheidend,char *malloc()
irgendwie zu erklären ; Es war entscheidend, das Ergebnis daraus auf einen anderen Zeigertyp zu übertragen. Die Besetzung hat tatsächlich die von der CPU verwendete Nummer geändert. (Es gab auch viel Freude, als der Hauptspeicher auf unseren Systemen von 1 MiB auf 2 MiB aktualisiert wurde - da der Kernel ungefähr 3/4 MiB verwendete, bedeutete dies, dass Benutzerprogramme 1 1/4 MiB vor dem Paging usw. verwenden konnten.)quelle
free()
auf S. 22 enthält . 177, die implizit zurückgibtint
.void
wurde einigen Systemen (vielleicht Unix System III) hinzugefügt, bevor der Standard veröffentlicht wurde, aber das war nicht Teil von C, als K & R 1st Edn (1978) geschrieben wurde. Eine Funktion, die keinen Wert zurückgegeben hat, wurde ohne Rückgabetyp deklariert (was bedeutet, dass sie zurückgegeben wurdeint
). 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 düster gescheitert, wie es ein Standard nicht getan hätte. C99 entfernte jedoch dieint
Regeln für "implizite " und "implizite Funktionsdeklaration". Nicht der gesamte Code der Welt hat aufgeholt.(void)
Besetzung fürprintf()
?Diese Besetzung wird nicht benötigt. Es wäre wahrscheinlich nicht zu der Zeit gewesen, als C in Form von C89 standardisiert worden war.
Wenn es gewesen wäre, wäre es auf eine implizite Erklärung zurückzuführen . Dies bedeutete normalerweise, dass die Person, die den Code schrieb, vergaß
#include <stdlib.h>
und ein statischer Analysator verwendet wurde. Dies ist nicht die beste Problemumgehung, und eine viel bessere Idee wäre gewesen, nur#include <stdlib.h>
stattdessen. Hier einige Formulierungen aus C89 zur impliziten Deklaration:Aber das ist seltsam, weil sie nicht das Ergebnis von
malloc
beidem übertragenmalloc
undfree
sich in derselben Header-Datei befinden.Es ist auch möglich, dass dies nur ein Fehler oder eine Möglichkeit ist, dem Leser mitzuteilen, dass
free
kein Ergebnis zurückgegeben wird.quelle
free
aber nicht fürmalloc
.