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, "...")
.
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:
Çağırmak perror
size errno
POSIX 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
), perror
ası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 perror
daha ö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 errno
ve daha sonra bunu başka herhangi bir özel hata mesajıyla birleştirebileceğinden benzer olduğunu unutmayın fprintf
.
strerror
parçacığı açısından güvenli olması için bir ayrıntı gerekli değildir. Aptalca ama standart bu. strerror_l
bunun yerine POSIX 2008 sistemlerinde drop-in yedek olarak kullanılabilir. strerror_r
eski sistemlerde de mevcuttur, ancak uyumsuz sürümleri olan bazı sistemlerde gerçekten kötü sorunları vardır.
perror
ekliyor '\n'
, böylece format olacak "%s\n"
, hayır?
strerror_s
aslında arayüz olarak çok da kötü değil.
_s
standarda 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 _s
işlevler yerine tüm işlev ailesinin kullanılması gerektiği propagandasıdır (derleyici uyarıları şeklinde) .
Oldukça farklı şeyler yapıyorlar.
Sen kullanmak perror()
bir mesaj yazdırmak stderr
iç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:stderr
perror()
perror(str);
eşdeğerdir
if (str)
fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
fprintf(stderr, "%s\n", strerror(errno));
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.
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
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
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.