ฉันควรใช้ perror (“ …”) และ fprintf (stderr,“ …”) เมื่อใด


105

อ่านหน้าคนและรหัสบางอย่างไม่ได้จริงๆช่วยฉันในการทำความเข้าใจความแตกต่างระหว่าง - หรือดีกว่าเมื่อฉันควรใช้ - หรือperror("...")fprintf(stderr, "...")

คำตอบ:


113

การโทร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ผ่านทาง


3
โอ้เข้าใจแล้วฟังก์ชัน perror จะทำงานแตกต่างกันไปขึ้นอยู่กับค่าของ errno 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
freeboy1015

6
รายละเอียดเดียวstrerrorไม่จำเป็นต้องปลอดภัยต่อเกลียว มันโง่ แต่นั่นคือมาตรฐาน strerror_lสามารถใช้แทนดรอปอินแทนบนระบบ POSIX 2008 ได้ strerror_rยังมีให้บริการในระบบเก่า แต่มีปัญหาที่น่ารังเกียจจริงๆกับบางระบบที่มีเวอร์ชันที่ไม่เป็นไปตามข้อกำหนด
R .. GitHub STOP HELPING ICE

เช่นเดียวกับ nitpick ฉันคิดว่าperrorเพิ่ม'\n'ในตอนท้ายดังนั้นรูปแบบจะเป็น"%s\n"ไม่?
Jens Gustedt

1
@R .. ฮ่าฉันมีแล้วและเท่าที่ฉันรู้ว่าพวกเขาไม่ได้จ่ายเงินให้ฉันสักอย่าง และเนื่องจาก MS ดูเหมือนจะตัดการสนับสนุน C โดยสิ้นเชิงในตอนท้ายฉันจะเป็นคนเดียว :) strerror_sจริงๆแล้วก็ไม่ได้แย่เกินไปสำหรับอินเทอร์เฟซ
Jens Gustedt

2
ตัดรองรับอย่างสมบูรณ์? ดูเหมือนพวกเขาหลอกคณะกรรมการอีกครั้ง การนำ_sขยะเข้าสู่มาตรฐานนั้นเป็นเกมของ MS ("หากคุณใช้อินเทอร์เฟซของเราเราจะพิจารณาทำให้ผลิตภัณฑ์ของเรารองรับมาตรฐานของคุณ") และแน่นอนว่าตอนนี้พวกเขาไม่ได้ทำตาม อันที่จริงฉันยอมรับว่าอินเทอร์เฟซเดียวนี้ไม่เลวในตัวเอง สิ่งที่ไม่ดีคือการโฆษณาชวนเชื่อ (ในรูปแบบของคำเตือนของคอมไพเลอร์) ว่าไลบรารีมาตรฐานส่วนใหญ่ "ไม่ปลอดภัย" และ_sควรใช้ฟังก์ชันทั้งหมดแทนฟังก์ชันมาตรฐาน
R .. GitHub STOP HELPING ICE

40

พวกเขาทำสิ่งที่ค่อนข้างแตกต่าง

คุณสามารถใช้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));

12

perror(const char *s): errnoพิมพ์สตริงคุณให้มันตามด้วยสตริงที่อธิบายถึงค่าปัจจุบันของ

stderr: เป็นสตรีมเอาต์พุตที่ใช้ในการส่งข้อความแสดงข้อผิดพลาดของคุณเองไปยัง (ค่าเริ่มต้นคือเทอร์มินัล)

เกี่ยวข้อง:

char *strerror(int errnum): ให้หมายเลขข้อผิดพลาดและจะส่งคืนสตริงข้อผิดพลาดที่เกี่ยวข้อง


2

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"


-2

ฟังก์ชัน Perror ใช้เวลามากขึ้นในการดำเนินการเรียกใช้จากพื้นที่ผู้ใช้ไปยังพื้นที่เคอร์เนลในขณะที่ fprintf เรียก goest ไปยัง api ไปยัง kernal

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.