Standar C mengamanatkan bahwa tidak ada fungsi perpustakaan standar C yang akan ditetapkan errno
ke nol. Kenapa ini?
Saya bisa memahaminya berguna untuk memanggil beberapa fungsi, dan hanya memeriksa errno
setelah yang terakhir - misalnya:
errno = 0;
double x = strtod(str1, NULL);
long y = strtol(str2, NULL);
if (errno)
// either "strtod" or "strtol" failed
else
// both succeeded
Namun, apakah ini tidak dianggap "praktik buruk"? Karena Anda hanya memeriksa errno
di akhir, Anda hanya tahu bahwa salah satu fungsi melakukan gagal, tetapi tidak yang berfungsi gagal. Apakah sekadar mengetahui bahwa sesuatu gagal cukup baik untuk sebagian besar program praktis?
Saya mencoba mencari berbagai dokumen Dasar Pemikiran, tetapi banyak dari mereka tidak memiliki banyak detail <errno.h>
.
errno
, Anda selalu dapat mengaturnya ke nol sendiri.errno
ke nilai bukan nol bahkan jika itu berhasil. (Mungkin menyebut beberapa fungsi lain yang gagal, tetapi itu bukan merupakan kegagalan dalam fungsi luar.)Jawaban:
Perpustakaan C tidak diatur
errno
ke 0 karena alasan historis 1 . POSIX tidak lagi mengklaim perpustakaannya tidak akan mengubah nilai jika berhasil, dan halaman manual Linux baru untukerrno.h
mencerminkan hal ini:The ANSI C Dasar Pemikiran menyatakan bahwa panitia merasa itu lebih praktis untuk mengadopsi dan standarisasi praktek yang ada menggunakan
errno
.Hampir selalu ada cara untuk memeriksa kesalahan di luar memeriksa jika telah
errno
diatur. Memeriksa apakah telaherrno
ditetapkan tidak selalu dapat diandalkan, karena beberapa panggilan memerlukan panggilan API terpisah untuk mendapatkan alasan kesalahan. Misalnya,ferror()
digunakan untuk memeriksa kesalahan jika Anda mendapatkan hasil pendek darifread()
ataufwrite()
.Cukup menarik, contoh Anda menggunakan
strtod()
adalah salah satu kasus di mana pengaturanerrno
ke 0 sebelum panggilan diperlukan untuk mendeteksi dengan benar jika kesalahan telah terjadi. Semua fungsistrto*()
string ke angka memiliki persyaratan ini, karena nilai kembali yang valid dikembalikan bahkan dalam menghadapi kesalahan.Kode di atas didasarkan pada perilaku
strtod()
seperti yang didokumentasikan di Linux . Standar C hanya menetapkan bahwa underflow tidak dapat mengembalikan nilai lebih besar dari positif terkecildouble
, dan apakah atau tidakerrno
diatur untukERANGE
implementasi didefinisikan 2 .Sebenarnya ada tulisan penasehat sertifikat yang luas yang merekomendasikan selalu menetapkan
errno
ke 0 sebelum panggilan perpustakaan dan memeriksa nilainya setelah panggilan menunjukkan kegagalan telah terjadi . Ini karena beberapa panggilan pustaka akan disetelerrno
meskipun panggilan itu sendiri berhasil 3 .1. Sebelumnya saya mengklaim itu untuk menghindari kesalahan dari panggilan sebelumnya. Saya tidak dapat menemukan bukti untuk mendukung klaim ini. Saya juga punya
printf()
contoh palsu .2. Terima kasih kepada @chux karena telah menunjukkan ini. Referensi adalah C.11 §7.22.1.3 ¶10.
3. Ditunjukkan oleh @KeithThompson dalam komentar.
sumber
errno
untukERANGE
adalah implementasi didefinisikan dalam kasus underflow, sebenarnya tidak ada cara yang portabel untuk mendeteksi underflow. Kode saya mengikuti apa yang saya temukan di halaman manual Linux di sistem saya.strto*
fungsi - fungsi itulah sebabnya saya bertanya apakah contoh saya akan dianggap sebagai praktik yang buruk, tetapi itu satu-satunya cara di manaerrno
tidak disetel ke nol akan bermanfaat, atau bahkan berlaku.errno
dapat diatur bahkan dalam kasus keberhasilan, jadi hanya menggunakan fakta yang ditetapkan tidak benar-benar indikator yang cukup baik bahwa kesalahan terjadi. Anda harus memeriksa hasil panggilan individu untuk mengetahui apakah ada kesalahan sama sekali.Anda dapat melakukan pemeriksaan kesalahan untuk kedua panggilan fungsi, jika Anda benar-benar peduli.
Karena kita tidak pernah tahu bagaimana fungsi mach dipanggil dalam suatu proses, bagaimana lib dapat mengatur errnos untuk setiap panggilan fungsi, Benar?
sumber
Secara sewenang-wenang mengubah errorno analog dengan 'menangkap dan menelan' pengecualian. Sebelum ada pengecualian yang akan menyebar melalui lapisan yang berbeda dari suatu program dan akhirnya mencapai titik di mana penelepon akan menangkap dan menanggapi pengecualian dengan cara tertentu atau dengan sederhana melewati tanggung jawab, ada errnos. Tidak mengubah kesalahan, kecuali jika Anda entah bagaimana menangani, mengesampingkan, memperlakukan sebagai tidak relevan, kesalahan, sangat penting untuk paradigma propagasi penanganan kesalahan generasi pertama ini.
sumber