Perror (“…”) ve fprintf (stderr, “…”) ne zaman kullanmalıyım?


105

Man sayfalarını ve bazı kodları okumak, arasındaki farkı anlamama gerçekten yardımcı olmadı - veya daha iyisi, ne zaman kullanmalıyım - perror("...")veya fprintf(stderr, "...").

Yanıtlar:


113

Çağırmak perrorsize errnoPOSIX sistem çağrıları tarafından yazılan bir yerel evre hata değeri olan yorumlanmış değeri verecektir (yani, her evre için kendi değeri vardır errno). Örneğin, bir arama yaptıysanız open()ve bir hata oluştuysa (yani, geri döndüyse -1), perrorasıl hatanın ne olduğunu görmek için hemen ardından arayabilirdiniz . Bu arada diğer sistem çağrılarını ararsanız, değerin errnoüzerine yazılacağını ve perrordaha önceki bir sistem çağrısı tarafından bir hata oluşturulmuşsa aramanın sorununuzu teşhis etmede herhangi bir faydası olmayacağını unutmayın.

fprintf(stderr, ...)diğer yandan kendi özel hata mesajlarınızı yazdırmak için kullanılabilir. Adresine yazdırarak stderr, hata raporlama çıktınızın gitmesi gereken "normal" çıktıyla karıştırılmasını önlersiniz stdout.

Bunun fprintf(stderr, "%s\n", strerror(errno)), perror(NULL)bir çağrının strerror(errno)yazdırılan dize değerini oluşturacağından errnove daha sonra bunu başka herhangi bir özel hata mesajıyla birleştirebileceğinden benzer olduğunu unutmayın fprintf.


3
oh, anladım. hata işlevi errno değerine bağlı olarak farklı çalışır. If you use a function that effects errno then it makes sense to use perror. Errno işlevini etkilemeyen ve sadece bir hata kodu döndüren bir işlev kullanıyorsanız, fprintf (stderr, fmt, ...) kullanmalısınız. Örneğin, bir dizge aralık dışındaysa strtol LONG_MAX veya LONG_MIN döndürür ve errno değerini ERANGE olarak ayarlar. Yani, aralık dışı olduğu için strtol başarısız olursa, perror kullanırım.
freeboy1015

6
İş strerrorparçacığı açısından güvenli olması için bir ayrıntı gerekli değildir. Aptalca ama standart bu. strerror_lbunun yerine POSIX 2008 sistemlerinde drop-in yedek olarak kullanılabilir. strerror_reski sistemlerde de mevcuttur, ancak uyumsuz sürümleri olan bazı sistemlerde gerçekten kötü sorunları vardır.
R .. GitHub BUZA YARDIM ETMEYİ DUR

ayrıca bir nitpick olarak, bence sonunda perrorekliyor '\n', böylece format olacak "%s\n", hayır?
Jens Gustedt

1
@R .., ha, zaten var ve bildiğim kadarıyla bana bir şey ödemiyorlar. Ve MS, C'ye olan desteğini tamamen kesiyor gibi göründüğü için, sonunda tek ben olacağım :) strerror_saslında arayüz olarak çok da kötü değil.
Jens Gustedt

2
Desteğin tamamen kesilmesi mi? Görünüşe göre komiteyi yine kandırmışlar. Önemsizliklerini _sstandarda sokmak temelde MS'in bir oyunuydu ("Arayüzlerimizi kullanırsanız, ürünlerimizin sizin standardınızı desteklemesini gerçekten düşüneceğiz.") Ve tabii ki artık bunu takip etmiyorlar. Aslında bu arayüzün kendi başına kötü olmadığını kabul ediyorum. Kötü olan, standart kitaplığın çoğunun "güvensiz" olduğu ve standart _sişlevler yerine tüm işlev ailesinin kullanılması gerektiği propagandasıdır (derleyici uyarıları şeklinde) .
R .. GitHub BUZA YARDIM ETMEYİ DUR

40

Oldukça farklı şeyler yapıyorlar.

Sen kullanmak perror()bir mesaj yazdırmak stderriçin o tekabül errno. Herhangi bir şeyi veya başka bir akışa fprintf()yazdırmak için kullanırsınız . çok özel bir baskı işlevidir:stderrperror()

perror(str);

eşdeğerdir

if (str)
    fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
    fprintf(stderr, "%s\n", strerror(errno));

12

perror(const char *s): verdiğiniz dizeyi ve ardından geçerli değerini açıklayan bir dizeyi yazdırır errno.

stderr: kendi hata mesajlarınızı yönlendirmek için kullanılan bir çıkış akışıdır (varsayılan olarak terminal içindir).

İlgili:

char *strerror(int errnum): ona bir hata numarası verin ve ilgili hata dizesini döndürür.


2

perror () her zaman stderr'e yazar; fprintf () ile birlikte kullanılan strerr (), herhangi bir çıktıya yazabilir - stderr dahil, ancak özel olarak değil.

fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")

Ayrıca, perror "metin: hata açıklaması" biçimlendiren kendi metnini empoze eder


-2

Perror işlevi yürütme işlemini gerçekleştirmek için daha fazla zaman alır, çağrı kullanıcı alanından kernal alana gider, fprintf çağrıları ise api'den kernal'e gider

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.