Membaca halaman manual dan beberapa kode tidak benar-benar membantu saya dalam memahami perbedaan antara - atau lebih baik, kapan saya harus menggunakan - perror("...")
atau fprintf(stderr, "...")
.
Membaca halaman manual dan beberapa kode tidak benar-benar membantu saya dalam memahami perbedaan antara - atau lebih baik, kapan saya harus menggunakan - perror("...")
atau fprintf(stderr, "...")
.
Jawaban:
Memanggil perror
akan memberi Anda nilai yang diinterpretasikan errno
, yang merupakan nilai kesalahan lokal-thread yang ditulis oleh sistem POSIX (yaitu, setiap thread memiliki nilainya sendiri untuk errno
). Misalnya, jika Anda membuat panggilan ke open()
, dan ada kesalahan yang dihasilkan (yaitu, kembali -1
), Anda kemudian dapat memanggil perror
segera setelah itu untuk melihat kesalahan yang sebenarnya. Perlu diingat bahwa jika Anda memanggil syscall lain untuk sementara, maka nilai di errno
akan ditimpa, dan panggilan perror
tidak akan berguna dalam mendiagnosis masalah Anda jika kesalahan dihasilkan oleh syscall sebelumnya.
fprintf(stderr, ...)
di sisi lain dapat digunakan untuk mencetak pesan kesalahan kustom Anda sendiri. Dengan mencetak ke stderr
, Anda menghindari keluaran pelaporan kesalahan Anda tercampur dengan keluaran "normal" yang seharusnya menjadi stdout
.
Perlu diingat bahwa fprintf(stderr, "%s\n", strerror(errno))
ini mirip dengan perror(NULL)
karena panggilan ke strerror(errno)
akan menghasilkan nilai string yang dicetak untuk errno
, dan Anda kemudian dapat menggabungkannya dengan pesan kesalahan khusus lainnya melalui fprintf
.
strerror
tidak perlu thread-safe. Itu bodoh, tapi itulah standarnya. strerror_l
dapat digunakan sebagai pengganti drop-in pada sistem POSIX 2008. strerror_r
juga tersedia pada sistem yang lebih lama tetapi memiliki masalah yang sangat buruk dengan beberapa sistem yang memiliki versi yang tidak sesuai.
perror
menambahkan '\n'
di akhir sehingga formatnya akan menjadi "%s\n"
, bukan?
strerror_s
sebenarnya tidak terlalu buruk sebagai antarmuka.
_s
sampah mereka ke standar pada dasarnya adalah permainan oleh MS ("Jika Anda mengadopsi antarmuka kami, kami akan mempertimbangkan untuk benar-benar membuat produk kami mendukung standar Anda.") Dan tentu saja sekarang mereka tidak menindaklanjuti. Sebenarnya saya setuju kalau interface yang satu ini sendiri tidak jelek. Yang buruk adalah propaganda (dalam bentuk peringatan kompilator) bahwa sebagian besar pustaka standar "tidak aman" dan bahwa seluruh keluarga _s
fungsi harus digunakan alih-alih yang standar.
Mereka melakukan hal-hal yang agak berbeda.
Anda gunakan perror()
untuk mencetak pesan stderr
yang sesuai dengan errno
. Anda gunakan fprintf()
untuk mencetak apa pun ke stderr
, atau aliran lainnya. perror()
adalah fungsi pencetakan yang sangat terspesialisasi:
perror(str);
setara dengan
if (str)
fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
fprintf(stderr, "%s\n", strerror(errno));
perror(const char *s)
: mencetak string yang Anda berikan diikuti dengan string yang menjelaskan nilai saat ini errno
.
stderr
: ini adalah aliran keluaran yang digunakan untuk menyalurkan pesan kesalahan Anda sendiri ke (default ke terminal).
Relevan:
char *strerror(int errnum)
: berikan nomor kesalahan, dan itu akan mengembalikan string kesalahan terkait.
perror () selalu menulis ke stderr; strerr (), digunakan bersama dengan fprintf (), dapat menulis ke keluaran apa pun - termasuk stderr tetapi tidak secara eksklusif.
fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")
Lebih lanjut, perror menerapkan format teksnya sendiri "teks: deskripsi kesalahan"
Fungsi perror membutuhkan lebih banyak waktu untuk melakukan panggilan eksekusi dari ruang pengguna ke ruang kernal sedangkan panggilan fprintf menuju api ke kernal
If you use a function that effects errno then it makes sense to use perror
Jika Anda menggunakan fungsi yang tidak mempengaruhi errno dan hanya mengembalikan kode kesalahan, Anda harus menggunakan fprintf (stderr, fmt, ...). Misalnya, strtol akan mengembalikan LONG_MAX atau LONG_MIN jika string di luar jangkauan dan menyetel errno ke ERANGE. Jadi jika strtol gagal karena di luar jangkauan, saya akan menggunakan perror.