อ่านหน้าคนและรหัสบางอย่างไม่ได้จริงๆช่วยฉันในการทำความเข้าใจความแตกต่างระหว่าง - หรือดีกว่าเมื่อฉันควรใช้ - หรือperror("...")
fprintf(stderr, "...")
อ่านหน้าคนและรหัสบางอย่างไม่ได้จริงๆช่วยฉันในการทำความเข้าใจความแตกต่างระหว่าง - หรือดีกว่าเมื่อฉันควรใช้ - หรือperror("...")
fprintf(stderr, "...")
คำตอบ:
การโทรperror
จะให้ค่าที่ตีความerrno
ซึ่งเป็นค่าความผิดพลาดของเธรดโลคัลที่เขียนโดย POSIX syscalls (กล่าวคือทุกเธรดมีค่าเป็นของตัวเองerrno
) ตัวอย่างเช่นหากคุณโทรไปopen()
และมีข้อผิดพลาดเกิดขึ้น (เช่นมีการส่งคืน-1
) คุณสามารถโทรติดต่อperror
ได้ทันทีเพื่อดูข้อผิดพลาดที่แท้จริง โปรดทราบว่าหากคุณโทรหา syscall อื่นในระหว่างนี้ค่าในerrno
จะถูกเขียนทับและการโทรperror
จะไม่มีประโยชน์ใด ๆ ในการวินิจฉัยปัญหาของคุณหากเกิดข้อผิดพลาดโดย syscall รุ่นก่อนหน้า
fprintf(stderr, ...)
ในทางกลับกันสามารถใช้เพื่อพิมพ์ข้อความแสดงข้อผิดพลาดของคุณเอง โดยการพิมพ์เพื่อstderr
คุณหลีกเลี่ยงการรายงานข้อผิดพลาดการส่งออกของคุณจะถูกผสมกับการส่งออก "ปกติ" stdout
ที่ควรจะไป
เก็บไว้ในใจว่าfprintf(stderr, "%s\n", strerror(errno))
จะคล้ายกับperror(NULL)
ตั้งแต่เรียกร้องให้strerror(errno)
จะสร้างค่าสตริงพิมพ์errno
และคุณสามารถรวมกันแล้วว่ามีข้อผิดพลาดที่กำหนดเองอื่น ๆ fprintf
ผ่านทาง
strerror
ไม่จำเป็นต้องปลอดภัยต่อเกลียว มันโง่ แต่นั่นคือมาตรฐาน strerror_l
สามารถใช้แทนดรอปอินแทนบนระบบ POSIX 2008 ได้ strerror_r
ยังมีให้บริการในระบบเก่า แต่มีปัญหาที่น่ารังเกียจจริงๆกับบางระบบที่มีเวอร์ชันที่ไม่เป็นไปตามข้อกำหนด
perror
เพิ่ม'\n'
ในตอนท้ายดังนั้นรูปแบบจะเป็น"%s\n"
ไม่?
strerror_s
จริงๆแล้วก็ไม่ได้แย่เกินไปสำหรับอินเทอร์เฟซ
_s
ขยะเข้าสู่มาตรฐานนั้นเป็นเกมของ MS ("หากคุณใช้อินเทอร์เฟซของเราเราจะพิจารณาทำให้ผลิตภัณฑ์ของเรารองรับมาตรฐานของคุณ") และแน่นอนว่าตอนนี้พวกเขาไม่ได้ทำตาม อันที่จริงฉันยอมรับว่าอินเทอร์เฟซเดียวนี้ไม่เลวในตัวเอง สิ่งที่ไม่ดีคือการโฆษณาชวนเชื่อ (ในรูปแบบของคำเตือนของคอมไพเลอร์) ว่าไลบรารีมาตรฐานส่วนใหญ่ "ไม่ปลอดภัย" และ_s
ควรใช้ฟังก์ชันทั้งหมดแทนฟังก์ชันมาตรฐาน
พวกเขาทำสิ่งที่ค่อนข้างแตกต่าง
คุณสามารถใช้perror()
ในการพิมพ์ข้อความไปยังสอดคล้องกับที่stderr
errno
คุณสามารถใช้fprintf()
พิมพ์อะไรไปstderr
หรือกระแสอื่น ๆ perror()
เป็นฟังก์ชันการพิมพ์ที่พิเศษมาก:
perror(str);
เทียบเท่ากับ
if (str)
fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
fprintf(stderr, "%s\n", strerror(errno));
perror(const char *s)
: errno
พิมพ์สตริงคุณให้มันตามด้วยสตริงที่อธิบายถึงค่าปัจจุบันของ
stderr
: เป็นสตรีมเอาต์พุตที่ใช้ในการส่งข้อความแสดงข้อผิดพลาดของคุณเองไปยัง (ค่าเริ่มต้นคือเทอร์มินัล)
เกี่ยวข้อง:
char *strerror(int errnum)
: ให้หมายเลขข้อผิดพลาดและจะส่งคืนสตริงข้อผิดพลาดที่เกี่ยวข้อง
perror () เขียนถึง stderr เสมอ strerr () ใช้ร่วมกับ fprintf () สามารถเขียนไปยังเอาต์พุตใดก็ได้ - รวมถึง stderr แต่ไม่เฉพาะ
fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")
นอกจากนี้ perror ยังกำหนดรูปแบบข้อความของตัวเองว่า "text: error description"
ฟังก์ชัน Perror ใช้เวลามากขึ้นในการดำเนินการเรียกใช้จากพื้นที่ผู้ใช้ไปยังพื้นที่เคอร์เนลในขณะที่ fprintf เรียก goest ไปยัง api ไปยัง kernal
If you use a function that effects errno then it makes sense to use perror
หากคุณใช้ฟังก์ชันที่ไม่มีผล errno และเพียงส่งคืนรหัสข้อผิดพลาดคุณควรใช้ fprintf (stderr, fmt, ... ) ตัวอย่างเช่น strtol จะส่งคืน LONG_MAX หรือ LONG_MIN หากสตริงอยู่นอกช่วงและตั้งค่า errno เป็น ERANGE ดังนั้นถ้า strtol ล้มเหลวเนื่องจากอยู่นอกระยะฉันจะใช้ perror