什么时候应该使用 perror("...") 和 fprintf(stderr, "...")?

Posted

技术标签:

【中文标题】什么时候应该使用 perror("...") 和 fprintf(stderr, "...")?【英文标题】:When should I use perror("...") and fprintf(stderr, "...")? 【发布时间】:2012-08-19 14:25:01 【问题描述】:

阅读手册页和一些代码并没有真正帮助我 了解 - 或更好,什么时候应该使用 - perror("...")fprintf(stderr, "...") 之间的区别。

【问题讨论】:

例如为什么要打印...: No such file or directory 【参考方案1】:

调用perror 将为您提供errno 的解释值,这是一个由POSIX 系统调用写入的线程本地错误值(即,每个线程都有自己的errno 值)。例如,如果您调用了open(),并且生成了一个错误(即,它返回了-1),那么您可以在之后立即调用perror 来查看实际的错误是什么。请记住,如果您同时调用其他系统调用,那么errno 中的值将被覆盖,如果早期的系统调用产生错误,则调用perror 将无法诊断您的问题.

另一方面,fprintf(stderr, ...) 可用于打印您自己的自定义错误消息。通过打印到stderr,您可以避免错误报告输出与应该发送到stdout 的“正常”输出混合。

请记住,fprintf(stderr, "%s\n", strerror(errno)) 类似于 perror(NULL),因为对 strerror(errno) 的调用将生成 errno 的打印字符串值,然后您可以通过 fprintf 将其与任何其他自定义错误消息相结合.

【讨论】:

哦,明白了。根据 errno 的值,perror 函数的工作方式不同。 If you use a function that effects errno then it makes sense to use perror.如果您使用的函数不会影响 errno 并仅返回错误代码,则应使用 fprintf(stderr, fmt, ...)。例如,如果字符串超出范围并将 errno 设置为 ERANGE,strtol 将返回 LONG_MAX 或 LONG_MIN。因此,如果 strtol 由于超出范围而失败,我会使用 perror。 一个细节,strerror 不需要是线程安全的。这很愚蠢,但这是标准。 strerror_l 可以用作 POSIX 2008 系统上的直接替代品。 strerror_r 也可用于较旧的系统,但在某些版本不符合要求的系统中存在非常严重的问题。 @R.. C11 有(将有:) strerror_s 作为线程安全的变体。 @R..,哈,我已经有了,据我所知,他们没有付钱给我。而且由于 MS 似乎完全停止了对 C 的支持,最后我将是唯一的一个 :) strerror_s 作为一个接口实际上还不错。 完全切断支持?看来他们又愚弄了委员会。让他们的 _s 垃圾进入标准基本上是 MS 的游戏(“如果你采用我们的接口,我们会考虑让我们的产品真正支持你的标准。”)当然现在他们没有遵循。其实我同意这个界面本身还不错。不好的是宣传(以编译器警告的形式)大多数标准库是“不安全的”,应该使用整个 _s 函数家族而不是标准函数。【参考方案2】:

他们做的事情完全不同。

您使用perror()stderr 打印与errno 对应的消息。您使用fprintf()anything 打印到stderr 或任何其他流。 perror() 是一个非常专业的打印功能:

perror(str);

等价于

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

【讨论】:

perror("")除外【参考方案3】:

perror(const char *s):打印你给它的字符串,后面跟着一个描述errno当前值的字符串。

stderr:它是一个输出流,用于将您自己的错误消息通过管道传送到(默认为终端)。

相关:

char *strerror(int errnum):给它一个错误号,它会返回相关的错误字符串。

【讨论】:

【参考方案4】:

perror() 总是写入标准错误; strerr() 与 fprintf() 一起使用,可以写入任何输出 - 包括 stderr,但不限于此。

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

此外,perror 强加了自己的文本格式“文本:错误描述”

【讨论】:

【参考方案5】:

perror 函数需要更多时间来执行执行调用从用户空间到内核空间而 fprintf 调用从 api 到内核

【讨论】:

以上是关于什么时候应该使用 perror("...") 和 fprintf(stderr, "...")?的主要内容,如果未能解决你的问题,请参考以下文章

什么时候应该使用 jQuery deferred 的“then”方法,什么时候应该使用“pipe”方法?

什么时候应该明确使用 StringBuilder? [复制]

servletcontext.getRealPath("/") 是啥意思,我应该啥时候使用它

内核中是不是有 perror 的等价物?

我啥时候应该使用“隐藏文本框”,啥时候应该使用(html 5)“数据属性”?

为啥 perror() 在重定向时会改变流的方向?