简体   繁体   English

perror()和printf()之间的区别

[英]Difference between perror() and printf()

I had read that both perror() and printf() write to the terminal screen. 我读过perror()printf()写入终端屏幕。 But perror() writes to stderr while printf() writes to stdout . 但是当printf()写入stdout时, perror()写入stderr So, to print errors why is perror() used when printf() can do it. 因此,要打印错误,为什么在printf()可以执行时使用perror()

printf() cannot write to stderr . printf()无法写入stderr fprintf() can. fprintf()可以。 perror() always does. perror()总是如此。

There is no requirement that writing to either stdout or stderr writes to a terminal screen - that is up to the implementation (since not all systems even have a terminal). 写入stdoutstderr并不要求写入终端屏幕 - 这取决于实现(因为并非所有系统都有终端)。 There is also no requirement that writing to stdout and stderr results in writing to the same device (eg one can be redirected to a file, while the other is redirected to a pipe). 写入stdoutstderr也没有要求写入同一设备(例如,一个可以重定向到文件,而另一个被重定向到管道)。

perror() will be implemented with built-in knowledge of the meanings of error codes, represented by the static errno , which is used by various functions in the standard library to report error conditions. perror()将通过内置的错误代码含义知识实现,由静态errno代表,静态错误代码由标准库中的各种函数用于报告错误情况。 The meanings of particular values are implementation defined (ie they vary between compilers and libraries). 特定值的含义是实现定义的(即它们在编译器和库之间有所不同)。

Because there could be configurations where you want stderr printed to the console but the other output not printed at all (for example, to remove verbosity). 因为可能存在需要将stderr打印到控制台但其他输出根本不打印的配置(例如,删除详细程度)。 In other cases you may need to redirect stderr to write to a file, this is useful when you are in production and that file can be used to understand what went wrong on a remote computer you can't debug yourself. 在其他情况下,您可能需要重定向stderr以写入文件,这在您进行生产时非常有用,并且该文件可用于了解您无法自行调试的远程计算机上出现的问题。

In general, you gain more control on how console outputs are treated depending on their type. 通常,您可以根据类型控制控制台输出的处理方式。

See this answer to understand how you can do stream redirection in code. 请参阅此答案以了解如何在代码中进行流重定向。

Or, see this link on how you can force stream redirection to file or ignore a stream on an already compiled program (while invoking it in bash ) 或者,请参阅此链接 ,了解如何强制流重定向到文件或忽略已编译程序上的流(在bash中调用它时)

In addition to other answers, you might use fprintf(3) on stderr and errno(3) with strerror(3) like 除了其他答案,你可以在stderrerrno(3)上使用fprintf(3)strerror(3)之类的

 fprintf(stderr, "something wrong: %s\n", strerror(errno));

On GNU libc systems (many Linux systems), you could use instead %m conversion specifier instead: 在GNU libc系统(许多Linux系统)上,您可以改为使用%m转换说明符:

fprintf(stderr, "something wrong: %m\n");

You conventionally should output error messages to stderr (see stderr(3) ); 您通常应该向stderr输出错误消息(请参阅stderr(3) ); see also syslog(3) to use system logging. 另请参阅syslog(3)以使用系统日志记录。

Don't forget to end the format string with \\n since stderr is often line buffered (but sometimes not) or else use fflush(3) 不要忘记用\\n结束格式字符串,因为stderr通常是行缓冲的(但有时不是)或者使用fflush(3)

For example, you might want to show both the error, the filename and the current directory on fopen failure: 例如,您可能希望在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
 }

Remember that errno could be overwritten by many failures (so we store it in e , in the unlikely case that getcwd fails and overwrite errno ). 请记住, errno可能被许多失败所覆盖(因此我们将其存储在e ,在不太可能的情况下getcwd失败并覆盖errno )。

If your program is a deamon (eg has called daemon(3) ) you'll better use system log (ie call openlog(3) after calling daemon ) since daemon can redirect stderr to /dev/null 如果您的程序是守护程序 (例如已调用守护程序(3) ),您最好使用系统日志(即调用daemon 调用openlog(3) ),因为daemon可以将stderr重定向到/dev/null

There are three standard stream stdin stdout stderr . 有三个标准流stdin stdout stderr You can refer to know what is important of different stream. 您可以参考知道不同流的重要性。

For error messages and diagnostics ,stderr is used , to print on stderr Perror is used. 对于错误消息和诊断,使用stderr,在stderr上打印使用Perror printf can not do that. printf无法做到这一点。 Perror is also used to handle errors from system call Perror还用于处理系统调用中的错误

fd = open (pathname, flags, mode);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}

You can refer more about this in book The linux programming interface 您可以在书籍Linux编程界面中详细了解这一点

void perror(const char *s)

Perror prints message in following sequence : Perror按以下顺序打印消息:

argument of s , a colon , a space , a short message concerning error whose error code currently in errno and newline s参数,冒号,空格,关于错误的短消息,其错误代码当前在errno和换行符中

In standard C if s is null pointer than only message will be printed . 在标准C中,如果s为空指针,则仅打印消息。 other things will be ignored 其他事情将被忽略

To understand more you can also refer page 332 of The complete reference C 要了解更多信息,您还可以参考完整参考文献C的第332页

A big advantage of using perror(): 使用perror()的一大优势:

It is sometimes very useful to redirect stdout into /dev/null to only have access to errors since the verbosity of stdout might hide the errors that we need to fix. stdout重定向到/ dev / null有时只能访问错误非常有用,因为stdout的详细程度可能会隐藏我们需要修复的错误。

perror PERROR

The general purpose of the function is to halt the execution process due to an error. 该函数的一般用途是由于错误而暂停执行过程。 The error message produced by perror is platform-depend. perror生成的错误消息是依赖于平台的。 You can also print your own error message also. 您也可以打印自己的错误消息。

printf 的printf

The general purpose of the function is to print message user defined and continue the execution. 该函数的一般用途是打印用户定义的消息并继续执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM