Fehler beim Überprüfen von fprintf beim Drucken in stderr

8

Gemäß den Dokumenten kann fprintf fehlschlagen und bei einem Fehler eine negative Zahl zurückgeben. Es gibt viele Situationen, in denen es sinnvoll wäre, diesen Wert zu überprüfen.

Normalerweise verwende ich fprintf, um Fehlermeldungen an stderr zu drucken. Mein Code sieht normalerweise ungefähr so ​​aus:

%Vor%

In diesen Fällen ist es immer noch möglich, dass fprintf fehlschlägt? Wenn ja, kann die Fehlermeldung irgendwie angezeigt werden oder gibt es eine zuverlässigere Alternative zu fprintf?

Falls nicht, muss fprintf überprüft werden, wenn es auf diese Weise verwendet wird?

    
Rupert Madden-Abbott 31.01.2011, 00:18
quelle

5 Antworten

12

Der C-Standard besagt, dass die Dateistreams stdin, stdout und stderr irgendwo verbunden sein sollen, aber sie geben natürlich nicht an, wo. Es ist durchaus möglich, ein Programm mit ihnen umgeleitet auszuführen:

%Vor%

Ihre Schreibvorgänge werden erfolgreich sein - aber die Informationen werden nirgendwohin gehen. Eine brutalere Art, Ihr Programm auszuführen, ist:

%Vor%

Dieses Mal wurde es ohne offene Dateiströme für stdout und stderr ausgeführt - entgegen dem Standard. Es liest im Beispiel immer noch von / dev / null, was bedeutet, dass es keine nützliche Dateneingabe von stdin erhält.

Viele Programme überprüfen nicht, ob die Standard-E / A-Kanäle geöffnet sind. Viele Programme überprüfen nicht, ob die Fehlermeldung erfolgreich geschrieben wurde. Entwerfen eines geeigneten Fallback als Umriss von Tim Post und whitey04 ist nicht immer die Mühe wert. Wenn Sie den Befehl ls mit seinen Ausgaben unterdrücken, wird er einfach das tun, was er kann, und mit einem Nicht-Null-Status beenden:

%Vor%

(Tested RHEL Linux.) Es gibt wirklich keine Notwendigkeit, mehr zu tun. Wenn Ihr Programm andererseits im Hintergrund läuft und in eine Protokolldatei schreibt, wird es wahrscheinlich nicht viel in stderr schreiben, es sei denn, es öffnet die Protokolldatei nicht (oder entdeckt einen Fehler in der Protokolldatei). .

Wenn Sie auf syslog(3) zurückgreifen (oder POSIX ), Sie können nicht wissen, ob Ihre Anrufe "erfolgreich" waren oder nicht; Die Syslog-Funktionen geben keine Statusinformationen zurück. Sie müssen nur annehmen, dass sie erfolgreich waren. Es ist daher Ihr letzter Ausweg.

    
Jonathan Leffler 31.01.2011, 01:03
quelle
9

Normalerweise würden Sie eine Art von Protokollierungssystem verwenden, das dies für Sie übernehmen könnte, oder Sie müssen diese Logik in jedem Bereich Ihres Codes duplizieren, der nach Standardfehler druckt und beendet.

Sie haben einige Optionen:

  • Wenn fprintf fehlschlägt, versuchen Sie syslog.
  • Wenn beide fehlschlagen, erstellen Sie eine 'crash. {pid} .log' Datei, die Informationen enthält, die Sie in einem Fehlerbericht haben möchten. Überprüfen Sie beim Start, ob diese Dateien vorhanden sind, da sie Ihrem Programm mitteilen können, dass es zuvor abgestürzt ist.
  • Lassen Sie die mit dem Netzwerk verbundenen Benutzer eine Konfigurationsoption prüfen, mit der Ihr Programm einen Fehlerbericht senden kann.

Übrigens sind open() read() und write() gute Freunde, wenn die fprintf-Familie von Funktionen nicht funktioniert.

Als whitey04 sagt , manchmal Sie gerade Ich muss aufgeben und mein Bestes tun, um nicht mit einem Feuerwerk zu verschmelzen. Aber versuchen Sie, diese Art von Logik in eine kleine Bibliothek zu isolieren.

Zum Beispiel:

%Vor%

Ist viel sauberer als eine Reihe von if else else if jeden Ort, wo Dinge möglicherweise schief gehen könnten.

    
Tim Post 31.01.2011 00:33
quelle
4

Sie könnten den Fehler auf "stdout" oder "woanders" setzen ... Irgendwann müssen Sie nur noch Fehler melden und dann aufgeben.

Der Schlüssel ist, dass Ihre App "elegant" damit zurechtkommt (z. B. muss das Betriebssystem es nicht als schlecht abtöten und es sagt Ihnen, warum es [wenn es möglich ist] beendet hat.)

    
whitey04 31.01.2011 00:26
quelle
3

Ja, natürlich kann fprintf bis stderr fehlschlagen. Zum Beispiel könnte stderr eine gewöhnliche Datei sein, und auf der Festplatte könnte kein Platz mehr sein, oder es könnte eine Pipe sein, die vom Leser geschlossen wird, usw.

Ob Sie einen Vorgang auf Fehler überprüfen sollten, hängt weitgehend davon ab, ob Sie durch Überprüfen ein besseres Programmverhalten erreichen können. In Ihrem Fall sind die einzigen denkbaren Dinge, die Sie tun könnten, wenn die Fehlermeldung nicht ausgegeben wird, einen anderen zu drucken (was höchstwahrscheinlich auch fehlschlägt) oder das Programm zu beenden (was wahrscheinlich schlimmer ist, als einen Fehler nicht zu melden, aber vielleicht nicht immer).

    
R.. 31.01.2011 05:08
quelle
2

Einige Programme, die wirklich Fehlermeldungen protokollieren möchten, richten beim Programmstart einen alternativen Stapel ein, um eine gewisse Menge an Speicherplatz zu reservieren (siehe sigaltstack(2) , das von einem Signalhandler (normalerweise SIGSEGV ) verwendet werden kann, um Fehler zu melden Wenn Sie Ihren Fehler protokollieren möchten, könnten Sie die Verwendung alternativer Stacks untersuchen, um einen Teil des Speichers vorab zuzuordnen. Es lohnt sich vielleicht nicht :) aber manchmal würden Sie alles für einen Hinweis geben, was passiert ist.

    
sarnold 31.01.2011 01:02
quelle

Tags und Links