fclose
erfordert als Argument eine FILE
Zeiger erhalten entweder durch fopen
, einer der Standard-Streams stdin
, stdout
, oder stderr
, oder auf eine andere implementierungsdefinierte Weise. Ein Nullzeiger gehört nicht dazu, daher ist das Verhalten undefiniert, genau wie bei fclose((FILE *)0xdeadbeef)
wäre. NULL ist nichts Besonderes in C; Abgesehen von der Tatsache, dass es garantiert ungleich mit jedem gültigen Zeiger vergleicht, ist es genau wie jeder andere ungültige Zeiger, und seine Verwendung ruft undefiniertes Verhalten hervor, außer wenn die Schnittstelle, die Sie es als Teil seines Vertrags an Dokumente übergeben, NULL
hat eine besondere Bedeutung.
Außerdem wäre die Rückgabe mit einem Fehler gültig (da das Verhalten sowieso undefiniert ist), aber schädliches Verhalten für eine Implementierung, weil es das undefinierte Verhalten verbirgt . Das bevorzugte Ergebnis des Aufrufs von undefiniertem Verhalten ist immer ein Absturz, da es den Fehler hervorhebt und es Ihnen ermöglicht, ihn zu beheben. Die meisten Benutzer von fclose
Suchen Sie nicht nach einem Fehlerrückgabewert, und ich würde wetten, dass die meisten Leute dumm genug sind, NULL
zu übergeben bis fclose
werden nicht schlau genug sein, den Rückgabewert von fclose
zu überprüfen . Man könnte argumentieren, dass Menschen sollten Überprüfen Sie den Rückgabewert von fclose
generell, da der finale Flush fehlschlagen könnte, aber das ist nicht nötig bei Dateien die nur zum Lesen geöffnet werden, oder wenn fflush
wurde vor fclose
manuell aufgerufen (Das ist sowieso eine klügere Redewendung, weil es einfacher ist, den Fehler zu behandeln, während Sie die Datei noch geöffnet haben).
fclose(NULL)
sollte erfolgreich. free(NULL)
erfolgreich ist, weil es dadurch einfacher wird, Bereinigungscode zu schreiben.
So wurde es leider nicht definiert. Daher können Sie fclose(NULL)
nicht verwenden in portablen Programmen. (Siehe z. B. http://pubs.opengroup.org/onlinepubs/9699919799/).
Wie andere bereits erwähnt haben, möchten Sie im Allgemeinen keinen Fehler zurückgeben, wenn Sie NULL an die falsche Stelle übergeben. Sie möchten eine Warnmeldung, zumindest bei Debug-/Test-Builds. Die Dereferenzierung von NULL gibt Ihnen eine sofortige Warnmeldung und die Möglichkeit, einen Backtrace zu sammeln, der den Programmierfehler identifiziert :). Während Sie programmieren, ist ein Segfault der beste Fehler, den Sie bekommen können. C hat viel mehr subtile Fehler, deren Fehlersuche viel länger dauert...
Es ist möglich, Fehlerrückgaben zu missbrauchen, um die Robustheit gegenüber Programmierfehlern zu erhöhen. Wenn Sie jedoch befürchten, dass ein Softwareabsturz Daten verlieren würde, beachten Sie, dass genau dasselbe passieren kann, z. wenn Ihre Hardware Strom verliert. Aus diesem Grund haben wir die automatische Speicherung (seit Unix-Texteditoren mit aus zwei Buchstaben bestehenden Namen wie ex und vi). Es wäre immer noch vorzuziehen, dass Ihre Software sichtbar abstürzt, anstatt mit einem inkonsistenten Zustand fortzufahren.
Die Fehler, von denen die Manpage spricht, sind Laufzeitfehler, keine Programmierfehler. Sie können NULL
nicht einfach weitergeben in jede API, die einen Zeiger erwartet, und erwarten, dass diese API etwas Vernünftiges tut. Übergeben eines NULL
Zeiger auf eine Funktion, die dokumentiert ist, dass sie einen Zeiger auf Daten erfordert, ist ein Fehler.
Verwandte Frage:Soll ich in C oder C++ Zeigerparameter gegen NULL/nullptr prüfen?
Um den Kommentar von R. zu einer der Antworten auf diese Frage zu zitieren:
... Sie scheinen Fehler, die sich aus außergewöhnlichen Bedingungen in der Betriebsumgebung ergeben (FS voll, Speichermangel, Netzwerkausfall usw.), mit Programmierfehlern zu verwechseln. Im ersteren Fall muss natürlich ein robustes Programm in der Lage sein, sie elegant zu handhaben. Im letzteren Fall kann ein robustes Programm sie überhaupt nicht erfahren.