【发布时间】:2015-12-05 09:00:23
【问题描述】:
我读到perror() 和printf() 都写入终端屏幕。但是perror() 写入stderr 而printf() 写入stdout。所以,要打印错误,为什么在 printf() 可以做到的情况下使用 perror()。
【问题讨论】:
我读到perror() 和printf() 都写入终端屏幕。但是perror() 写入stderr 而printf() 写入stdout。所以,要打印错误,为什么在 printf() 可以做到的情况下使用 perror()。
【问题讨论】:
printf() 无法写入stderr。 fprintf()可以。 perror() 总是这样。
没有要求写入stdout 或stderr 写入终端屏幕 - 这取决于实现(因为并非所有系统都具有终端)。也没有要求写入 stdout 和 stderr 会导致写入同一设备(例如,一个可以重定向到文件,而另一个重定向到管道)。
perror() 将使用内置的错误代码含义知识实现,由静态errno 表示,标准库中的各种函数使用它来报告错误情况。特定值的含义由实现定义(即它们在编译器和库之间有所不同)。
【讨论】:
因为可能存在您希望将stderr 打印到控制台但根本不打印其他输出的配置(例如,删除冗长)。在其他情况下,您可能需要重定向 stderr 以写入文件,这在您处于生产环境时很有用,并且该文件可用于了解您无法自行调试的远程计算机上出现的问题。
通常,您可以更好地控制控制台输出的处理方式,具体取决于它们的类型。
请参阅this answer 了解如何在代码中进行流重定向。
或者,请参阅this link,了解如何强制流重定向到文件或忽略已编译程序上的流(在 bash 中调用它时)
【讨论】:
除了其他答案之外,您还可以在stderr 和errno(3) 上使用fprintf(3) 和strerror(3) 类似
fprintf(stderr, "something wrong: %s\n", strerror(errno));
在 GNU libc 系统(许多 Linux 系统)上,您可以改用 %m 转换说明符:
fprintf(stderr, "something wrong: %m\n");
您通常应该将错误消息输出到stderr(请参阅stderr(3));另请参阅 syslog(3) 以使用系统日志记录。
不要忘记以\n 结束格式字符串,因为stderr 通常是行缓冲的(但有时不是),否则使用fflush(3)
例如,您可能希望在fopen 失败时同时显示错误、文件名和当前目录:
char* filename = somefilepath();
assert (filename != NULL);
FILE* f = fopen(filename, "r");
if (!f) {
int e = errno; // keep errno, it could be later overwritten
if (filename[0] == '/') /// absolute path
fprintf(stderr, "failed to open %s : %s\n", filename, strerror(e));
else { // we also try to show the current directory since relative path
char dirbuf[128];
memset (dirbuf, 0, sizeof(dirbuf));
if (getcwd(dirbuf, sizeof(dirbuf)-1))
fprintf(stderr, "failed to open %s in %s : %s\n",
filename, dirbuf, sterror(e));
else // unlikely case when getcwd failed so errno overwritten
fprintf(stderr, "failed to open %s here : %s\n",
filename, sterror(e));
};
exit(EXIT_FAILURE); // in all cases when fopen failed
}
请记住,errno 可能会被许多失败覆盖(因此我们将其存储在 e 中,在不太可能的情况下 getcwd 失败并覆盖 errno)。
如果你的程序是一个守护进程(例如调用了daemon(3)),你最好使用系统日志(即调用openlog(3)之后调用daemon),因为daemon可以重定向stderr 到/dev/null
【讨论】:
共有三个标准流stdinstdoutstderr。您可以refer 了解不同流的重要内容。
对于错误消息和诊断,使用stderr,在stderr上打印 使用了错误。 printf 不能那样做。 Perror 也用于处理来自系统调用的错误
fd = open (pathname, flags, mode);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
您可以在本书The linux programming interface中参考更多信息
void perror(const char *s)
Perror 按以下顺序打印消息:
s的参数,一个冒号,一个空格,一条关于错误的短消息,其错误代码当前在errno和换行符
在标准 C 中,如果 s 是空指针,则只会打印消息。其他的会被忽略
要了解更多您也可以参考The complete reference C的第332页
【讨论】:
使用 perror() 的一大优势:
有时将 stdout 重定向到 /dev/null 以仅访问错误非常有用,因为 stdout 的冗长可能会隐藏我们需要修复的错误.
【讨论】:
该函数的一般用途是由于错误而停止执行过程。 perror 产生的错误信息是平台相关的。您也可以打印自己的错误消息。
该函数的一般用途是打印用户定义的消息并继续执行。
【讨论】:
perror()根本没有停止程序。