ห้องสมุด C ไม่ได้ตั้งค่าerrno
เป็น 0 เพื่อเหตุผลทางประวัติศาสตร์1 POSIX ไม่อ้างว่าห้องสมุดจะไม่เปลี่ยนค่าในกรณีที่ประสบความสำเร็จอีกต่อไปและหน้าลินุกซ์ใหม่สำหรับการerrno.h
สะท้อนสิ่งนี้:
<errno.h>
ไฟล์ส่วนหัวกำหนดตัวแปรจำนวนเต็มerrno
ซึ่งถูกกำหนดโดยสายระบบและบางฟังก์ชั่นห้องสมุดในกรณีที่มีข้อผิดพลาดในการบ่งบอกถึงสิ่งที่ผิดไป ค่าของมันมีความสำคัญเฉพาะเมื่อค่าส่งคืนของการโทรระบุข้อผิดพลาด (เช่น-1
จากการเรียกของระบบส่วนใหญ่-1
หรือNULL
จากฟังก์ชั่นห้องสมุดส่วนใหญ่); ฟังก์ชั่นที่ประสบความสำเร็จจะerrno
ได้รับอนุญาตให้มีการเปลี่ยนแปลง
ANSI C เหตุผลerrno
ระบุว่าคณะกรรมการรู้สึกว่ามันเป็นจริงมากขึ้นเพื่อนำมาใช้และมาตรฐานการปฏิบัติที่มีอยู่ของการใช้
เครื่องจักรการรายงานข้อผิดพลาดที่มีศูนย์กลางเกี่ยวกับการตั้งค่าerrno
นั้นโดยทั่วไปถือว่ามีความอดทนที่ดีที่สุด มันต้องใช้ `` พยาธิวิทยาการเชื่อมต่อ '' ระหว่างฟังก์ชั่นห้องสมุดและใช้ประโยชน์จากเซลล์หน่วยความจำแบบเขียนได้แบบสแตติกซึ่งรบกวนการสร้างไลบรารีแบบแบ่งใช้ อย่างไรก็ตามคณะกรรมการมีความประสงค์ที่จะสร้างมาตรฐานที่มีอยู่ในปัจจุบัน แต่มีข้อบกพร่องเครื่องจักรมากกว่าที่จะคิดค้นสิ่งที่มีความทะเยอทะยานมากขึ้น
มีวิธีการตรวจสอบข้อผิดพลาดนอกเหนือจากการตรวจสอบเกือบทุกครั้งหากerrno
ตั้งค่าไว้ การตรวจสอบว่าerrno
ชุดที่ตั้งไว้ไม่น่าเชื่อถือเสมอไปหรือไม่เนื่องจากการโทรบางครั้งจำเป็นต้องเรียก API แยกต่างหากเพื่อรับเหตุผลข้อผิดพลาด ยกตัวอย่างเช่นferror()
จะใช้ในการตรวจสอบข้อผิดพลาดถ้าคุณได้รับผลระยะสั้น ๆ จากหรือfread()
fwrite()
ที่น่าสนใจพอตัวอย่างของคุณของการใช้strtod()
เป็นหนึ่งในกรณีที่การตั้งค่าerrno
ให้เป็น 0 ก่อนที่สายจะต้องให้ถูกต้องตรวจสอบได้หากมีข้อผิดพลาดเกิดขึ้น ทั้งหมดstrto*()
สตริงฟังก์ชั่นมีความต้องการจำนวนนี้เพราะค่าตอบแทนที่ถูกต้องจะถูกส่งกลับแม้ในใบหน้าของข้อผิดพลาด
errno = 0;
char *endptr;
double x = strtod(str1, &endptr);
if (endptr == str1) {
/*...parse error */
} else if (errno == ERANGE) {
if (x == 0) {
/*...underflow */
} else if (x == HUGE_VAL) {
/*...positive overflow */
} else if (x == -HUGE_VAL) {
/*...negative overflow */
} else {
/*...unknown range error? */
}
}
รหัสดังกล่าวจะขึ้นอยู่กับลักษณะการทำงานของstrtod()
การบันทึกไว้บน Linux มาตรฐาน C เท่านั้นกำหนดว่า underflow ไม่สามารถกลับมากขึ้นคุ้มค่ากว่าในเชิงบวกที่เล็กที่สุดdouble
และไม่ว่าจะได้หรือไม่errno
ถูกตั้งค่าให้ERANGE
มีการดำเนินงานที่กำหนดไว้2
มีจริงกว้างขวางCERT Advisory เขียนขึ้นที่แนะนำเสมอการตั้งค่าerrno
ให้เป็น 0 ก่อนที่จะโทรห้องสมุดและการตรวจสอบความคุ้มค่าหลังจากที่โทรแสดงให้เห็นความล้มเหลวที่เกิดขึ้น เพราะนี่คือบางสายห้องสมุดจะตั้งerrno
แม้ว่าการเรียกตัวเองประสบความสำเร็จ3
ค่าerrno
เป็น 0 เมื่อเริ่มต้นโปรแกรม แต่ไม่เคยถูกตั้งค่าเป็น 0 โดยฟังก์ชันไลบรารีใด ๆ ค่าของerrno
อาจถูกตั้งค่าเป็นไม่ใช่ศูนย์โดยการเรียกฟังก์ชันไลบรารีว่ามีข้อผิดพลาดหรือไม่หากการใช้งานerrno
ไม่ได้บันทึกไว้ในคำอธิบายของฟังก์ชันใน C Standard มันมีความหมายสำหรับโปรแกรมที่จะตรวจสอบเนื้อหาerrno
หลังจากที่รายงานข้อผิดพลาดแล้วเท่านั้น แม่นยำยิ่งขึ้นerrno
มีความหมายเฉพาะหลังจากฟังก์ชันไลบรารีที่ตั้งค่าความerrno
ผิดพลาดได้ส่งคืนรหัสข้อผิดพลาด
1. ก่อนหน้านี้ฉันอ้างว่าเพื่อหลีกเลี่ยงการปิดบังข้อผิดพลาดจากการโทรก่อนหน้านี้ ฉันไม่พบหลักฐานใด ๆ ที่สนับสนุนข้อเรียกร้องนี้ ฉันยังมีprintf()
ตัวอย่างปลอม
2. ขอบคุณ @chux ที่ชี้เรื่องนี้ออกมา การอ้างอิงคือ C.11 §7.22.1.3¶10
3. ชี้โดย @KeithThompson ในความคิดเห็น
errno
คุณสามารถตั้งค่าให้เป็นศูนย์ด้วยตัวเอง