Das Lesen der Manpages und eines Codes hat mir nicht wirklich geholfen, den Unterschied zwischen - oder besser, wann ich es verwenden sollte - perror("...")
oder zu verstehen fprintf(stderr, "...")
.
Das Lesen der Manpages und eines Codes hat mir nicht wirklich geholfen, den Unterschied zwischen - oder besser, wann ich es verwenden sollte - perror("...")
oder zu verstehen fprintf(stderr, "...")
.
Antworten:
Der Aufruf perror
wird Ihnen das interpretiert Wert errno
, der einen lokalen Thread-Fehlerwert von POSIX syscalls geschrieben ist (dh jeder Thread für seinen eigenen Wert hat errno
). Wenn Sie beispielsweise einen Anruf getätigt open()
haben und ein Fehler generiert wurde (dh zurückgegeben wurde -1
), können Sie perror
sofort danach anrufen , um den tatsächlichen Fehler zu ermitteln. Beachten Sie, dass beim Aufrufen anderer Systemaufrufe in der Zwischenzeit der Wert in überschrieben errno
wird und das Aufrufen perror
bei der Diagnose Ihres Problems nicht hilfreich ist, wenn ein Fehler durch einen früheren Systemaufruf generiert wurde.
fprintf(stderr, ...)
Auf der anderen Seite können Sie Ihre eigenen benutzerdefinierten Fehlermeldungen drucken. Durch Drucken auf stderr
vermeiden Sie, dass Ihre Fehlerberichtsausgabe mit der "normalen" Ausgabe gemischt wird, die verwendet werden soll stdout
.
Beachten Sie, dass dies fprintf(stderr, "%s\n", strerror(errno))
ähnlich ist, perror(NULL)
da ein Aufruf von strerror(errno)
den gedruckten Zeichenfolgenwert für generiert errno
und Sie diesen dann mit jeder anderen benutzerdefinierten Fehlermeldung über kombinieren können fprintf
.
strerror
nicht threadsicher sein. Es ist dumm, aber das ist der Standard. strerror_l
kann stattdessen als Drop-In-Ersatz auf POSIX 2008-Systemen verwendet werden. strerror_r
ist auch auf älteren Systemen verfügbar, hat jedoch bei einigen Systemen mit nicht konformen Versionen wirklich schlimme Probleme.
perror
fügt '\n'
am Ende hinzu, so dass das Format wäre "%s\n"
, nein?
strerror_s
ist eigentlich keine schlechte Schnittstelle.
_s
Müll in den Standard zu bringen, war im Grunde ein Spiel von MS ("Wenn Sie unsere Schnittstellen übernehmen, werden wir in Betracht ziehen, unsere Produkte tatsächlich dazu zu bringen, Ihren Standard zu unterstützen.") Und natürlich folgen sie jetzt nicht mehr. Eigentlich stimme ich zu, dass diese eine Schnittstelle an sich nicht schlecht ist. Was schlecht ist, ist die Propaganda (in Form von Compiler-Warnungen), dass der größte Teil der Standardbibliothek "unsicher" ist und dass die gesamte _s
Funktionsfamilie anstelle der Standardfunktionen verwendet werden sollte.
Sie machen ziemlich unterschiedliche Dinge.
Sie verwenden perror()
, um eine Nachricht zu drucken, stderr
die entspricht errno
. Sie verwenden fprintf()
drucken etwas zu stderr
oder über anderen Strom. perror()
ist eine sehr spezielle Druckfunktion:
perror(str);
ist äquivalent zu
if (str)
fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
fprintf(stderr, "%s\n", strerror(errno));
perror(const char *s)
: Gibt die Zeichenfolge aus, die Sie ihm geben, gefolgt von einer Zeichenfolge, die den aktuellen Wert von beschreibt errno
.
stderr
: Es ist ein Ausgabestream, an den Sie Ihre eigenen Fehlermeldungen weiterleiten (standardmäßig an das Terminal).
Relevant:
char *strerror(int errnum)
: Geben Sie eine Fehlernummer ein, und die zugehörige Fehlerzeichenfolge wird zurückgegeben.
perror () schreibt immer in stderr; strerr () kann zusammen mit fprintf () in jede Ausgabe schreiben - einschließlich stderr, aber nicht ausschließlich.
fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")
Darüber hinaus legt perror einen eigenen Text fest, der "text: error description" formuliert.
Die Perror-Funktion benötigt mehr Zeit, um einen Ausführungsaufruf auszuführen, der vom Benutzerbereich zum Kernalbereich wechselt, während fprintf-Aufrufe von API zu Kernal gehen
If you use a function that effects errno then it makes sense to use perror
Wenn Sie eine Funktion verwenden, die errno nicht beeinflusst und einfach einen Fehlercode zurückgibt, sollten Sie fprintf (stderr, fmt, ...) verwenden. Beispielsweise gibt strtol LONG_MAX oder LONG_MIN zurück, wenn eine Zeichenfolge außerhalb des Bereichs liegt, und setzt errno auf ERANGE. Wenn strtol aufgrund eines Bereichs außerhalb des Bereichs fehlschlägt, würde ich perror verwenden.