Czytanie stron podręcznika man i części kodu tak naprawdę nie pomogło mi w zrozumieniu różnicy między - lub lepiej, kiedy powinienem używać - perror("...")
lub fprintf(stderr, "...")
.
Wywołanie perror
da ci zinterpretowaną wartość errno
, która jest wartością błędu lokalnego dla wątku zapisywaną przez wywołania systemowe POSIX (tj. Każdy wątek ma swoją własną wartość dla errno
). Na przykład, jeśli wykonałeś wywołanie open()
i wystąpił błąd (tj. Zwrócił -1
), możesz następnie zadzwonić perror
natychmiast po tym, aby zobaczyć, jaki był rzeczywisty błąd. Należy pamiętać, że jeśli w międzyczasie wywołasz inne wywołania systemowe, wartość w errno
zostanie nadpisana, a wywołanie perror
nie będzie przydatne w diagnozowaniu problemu, jeśli błąd został wygenerowany przez wcześniejsze wywołanie systemowe .
fprintf(stderr, ...)
z drugiej strony może służyć do drukowania własnych niestandardowych komunikatów o błędach. Drukując do stderr
, unikniesz pomieszania wyników raportowania błędów z "normalnymi" wynikami, które powinny się pojawić stdout
.
Należy pamiętać, że fprintf(stderr, "%s\n", strerror(errno))
jest to podobne do, perror(NULL)
ponieważ wywołanie funkcji strerror(errno)
wygeneruje wydrukowaną wartość ciągu dla errno
, którą można następnie połączyć z dowolnym innym niestandardowym komunikatem o błędzie za pośrednictwem fprintf
.
If you use a function that effects errno then it makes sense to use perror
Jeśli używasz funkcji, która nie wywołuje efektu errno i po prostu zwraca kod błędu, powinieneś użyć fprintf (stderr, fmt, ...). Na przykład strtol zwróci LONG_MAX lub LONG_MIN, jeśli łańcuch jest poza zakresem i ustawi errno na ERANGE. Więc jeśli strtol zawiedzie z powodu braku zasięgu, użyłbym perror.strerror
nie jest wymagany, aby był bezpieczny dla wątków. To głupie, ale to standard.strerror_l
może być używany jako zamiennik typu drop-in w systemach POSIX 2008.strerror_r
jest również dostępny na starszych systemach, ale ma naprawdę nieprzyjemne problemy z niektórymi systemami z niezgodnymi wersjami.perror
dodaje'\n'
na końcu więc format byłby"%s\n"
, nie?strerror_s
nie jest tak zły jako interfejs._s
śmieci do standardu było w zasadzie grą MS („Jeśli zaadoptujesz nasze interfejsy, rozważymy, czy nasze produkty będą obsługiwać Twój standard”) i oczywiście teraz nie nadążają. Właściwie zgadzam się, że ten jeden interfejs sam w sobie nie jest zły. Zła to propaganda (w postaci ostrzeżeń kompilatora), że większość biblioteki standardowej jest „niebezpieczna” i że_s
zamiast standardowych należy używać całej rodziny funkcji.Robią raczej różne rzeczy.
Używasz
perror()
do drukowania wiadomości,stderr
która odpowiadaerrno
. Używaszfprintf()
do drukowania czegokolwiek dostderr
lub dowolnego innego strumienia.perror()
to bardzo wyspecjalizowana funkcja drukowania:jest równa
źródło
perror(const char *s)
: wypisuje podany ciąg, po którym następuje ciąg opisujący bieżącą wartośćerrno
.stderr
: jest to strumień wyjściowy używany do przesyłania własnych komunikatów o błędach (domyślnie do terminala).Istotnych:
char *strerror(int errnum)
: nadaj mu numer błędu, a zwróci powiązany ciąg błędu.źródło
perror () zawsze zapisuje na stderr; strerr (), używana razem z fprintf (), może zapisywać na dowolnym wyjściu - w tym stderr, ale nie wyłącznie.
Ponadto perror narzuca swój własny tekst, tworząc tekst „tekst: opis błędu”
źródło
Funkcja Perror zajmuje więcej czasu, aby wykonać wywołanie przechodzi z przestrzeni użytkownika do przestrzeni jądra, podczas gdy wywołania fprintf przechodzą do api do kernal
źródło