อ่านหน้าคนและรหัสบางอย่างไม่ได้จริงๆช่วยฉันในการทำความเข้าใจความแตกต่างระหว่าง - หรือดีกว่าเมื่อฉันควรใช้ - หรือ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