Khi nào tôi nên sử dụng perror (“…”) và fprintf (stderr, “…”)?


105

Đọc các trang người dùng và một số mã không thực sự giúp tôi hiểu được sự khác biệt giữa - hoặc tốt hơn, khi nào tôi nên sử dụng - perror("...")hoặc fprintf(stderr, "...").

Câu trả lời:


113

Việc gọi perrorsẽ cung cấp cho bạn giá trị đã diễn giải errno, là giá trị lỗi cục bộ của luồng được ghi bởi các cuộc gọi hệ thống POSIX (tức là mỗi luồng đều có giá trị riêng của nó errno). Ví dụ: nếu bạn thực hiện một cuộc gọi đến open()và có một lỗi được tạo ra (tức là nó bị trả về -1), thì bạn có thể gọi perrorngay sau đó để xem lỗi thực sự là gì. Hãy nhớ rằng nếu bạn gọi các cuộc gọi tổng hợp khác trong thời gian chờ đợi, thì giá trị trong errnosẽ được ghi lại và việc gọi perrorsẽ không có ích gì trong việc chẩn đoán sự cố của bạn nếu một cuộc gọi tổng hợp trước đó đã xảy ra lỗi.

fprintf(stderr, ...)mặt khác có thể được sử dụng để in các thông báo lỗi tùy chỉnh của riêng bạn. Bằng cách in tới stderr, bạn tránh được kết quả báo cáo lỗi của mình bị trộn lẫn với đầu ra "bình thường" sẽ xảy ra stdout.

Hãy nhớ rằng điều đó fprintf(stderr, "%s\n", strerror(errno))tương tự như perror(NULL)vì lệnh gọi tới strerror(errno)sẽ tạo ra giá trị chuỗi được in cho errnovà sau đó bạn có thể kết hợp giá trị đó với bất kỳ thông báo lỗi tùy chỉnh nào khác qua fprintf.


3
Ồ, hiểu rồi. Hàm perror hoạt động khác nhau tùy thuộc vào giá trị của errno. If you use a function that effects errno then it makes sense to use perrorNếu bạn sử dụng một hàm không có hiệu lực errno và chỉ trả về mã lỗi, bạn nên sử dụng fprintf (stderr, fmt, ...). Ví dụ: strtol sẽ trả về LONG_MAX hoặc LONG_MIN nếu một chuỗi nằm ngoài phạm vi và đặt errno thành ERANGE. Vì vậy, nếu strtol không thành công do nằm ngoài phạm vi, tôi sẽ sử dụng lỗi.
freeboy1015

6
Một chi tiết, strerrorkhông bắt buộc phải an toàn cho chủ đề. Thật ngu ngốc, nhưng đó là tiêu chuẩn. strerror_lcó thể được sử dụng thay thế như một sự thay thế thả vào trên hệ thống POSIX 2008. strerror_rcũng có sẵn trên các hệ thống cũ hơn nhưng có vấn đề thực sự khó chịu với một số hệ thống có phiên bản không phù hợp của nó.
R .. GitHub DỪNG TRỢ GIÚP LÚC NỮA

cũng như một nitpick, tôi nghĩ perrorthêm '\n'vào cuối để định dạng sẽ là "%s\n", không?
Jens Gustedt

1
@R .., ha, tôi đã có, và theo như tôi biết thì họ không trả tiền cho tôi. Và vì MS dường như cắt hỗ trợ hoàn toàn cho C, nên cuối cùng tôi sẽ là người duy nhất :) strerror_sthực sự không quá tệ về giao diện.
Jens Gustedt

2
Hỗ trợ cắt hoàn toàn? Có vẻ như họ đã đánh lừa ủy ban một lần nữa. Đưa _srác của họ vào tiêu chuẩn về cơ bản là một trò chơi của MS ("Nếu bạn chấp nhận giao diện của chúng tôi, chúng tôi sẽ xem xét việc thực sự làm cho các sản phẩm của chúng tôi hỗ trợ tiêu chuẩn của bạn.") Và tất nhiên bây giờ họ không tuân theo. Trên thực tế, tôi đồng ý rằng một giao diện này không phải là xấu. Điều tồi tệ là tuyên truyền (dưới dạng cảnh báo trình biên dịch) rằng hầu hết các thư viện chuẩn là "không an toàn" và toàn bộ họ _shàm nên được sử dụng thay vì các hàm chuẩn.
R .. GitHub DỪNG TRỢ GIÚP ICE

40

Họ làm những việc khác nhau.

Bạn sử dụng perror()để in một tin nhắn stderrtương ứng với errno. Bạn sử dụng fprintf()để in bất cứ điều gì để stderr, hoặc bất kỳ dòng khác. perror()là một chức năng in rất chuyên biệt:

perror(str);

tương đương với

if (str)
    fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
    fprintf(stderr, "%s\n", strerror(errno));

12

perror(const char *s): in chuỗi mà bạn cung cấp, theo sau là một chuỗi mô tả giá trị hiện tại của errno.

stderr: đó là một luồng đầu ra được sử dụng để chuyển các thông báo lỗi của riêng bạn đến (mặc định là thiết bị đầu cuối).

Liên quan, thích hợp:

char *strerror(int errnum): cung cấp cho nó một số lỗi và nó sẽ trả về chuỗi lỗi liên quan.


2

perror () luôn ghi vào stderr; strerr (), được sử dụng cùng với fprintf (), có thể ghi vào bất kỳ đầu ra nào - bao gồm cả stderr nhưng không dành riêng.

fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")

Hơn nữa, perror áp đặt định dạng văn bản của riêng nó "text: error description"


-2

Hàm Perror mất nhiều thời gian hơn để thực hiện lệnh gọi thực thi đi từ không gian người dùng sang không gian kernal khi các lệnh gọi fprintf goest đến api đến kernal

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.