【问题标题】:Why doesn't c program print error message to stderr when system call fails?为什么系统调用失败时c程序不向stderr打印错误消息?
【发布时间】:2020-03-03 13:56:36
【问题描述】:

下面是简单c代码的sn-p:

#include <stdio.h>

int main(void) {
  FILE *fd = fopen("nothing", "r");
  // perror("fopen");
  return 0;
}

它什么也不打印,但如果 perror("fopen") 未注释,它会打印

fopen: No such file or directory

根据perror的手册页

当系统调用失败时,通常返回-1并设置变量 errno 到一个描述出了什么问题的值。

No such file or directory对应errno = 2

由于stderr是无缓冲的,似乎只有在调用perror时才会将错误消息写入stderr,为什么c程序会隐式忽略错误(errno已修改)而不是立即写入发给stderr

其他问题... 还有其他方法可以触发stderr的写作吗?我们是否总是必须“手动”触发它,还是 c 程序在某些情况下可以“自动”使其像 java 抛出运行时异常一样?

【问题讨论】:

  • 什么?当然,如果没有调用perror(),它不会打印错误?我不明白。
  • @unwind errno 设置为2 无论perror() 是否被调用,所以确实会发生错误
  • 是的,但是通过查看fopenerrno 的返回值,您可以知道。程序员可以决定是否进行通信以及如何处理此错误,因为您知道它是否严重。
  • 我不确定是否最好打开一个新问题而不是使用旧问题作为额外问题,特别是因为已经有一个解决原始问题的答案。跨度>
  • 至于您的额外问题:您始终可以编写行为类似于库函数的包装函数,如果出现问题则记录错误。 (是的,标准库中有很多函数,但您可以在需要时随时创建包装器。)

标签: c system-calls errno


【解决方案1】:

未能打开一个不存在的文件不是“系统错误”,- 成功打开一个不存在的文件将是一个错误!

使用fopen() 测试文件是否存在可能是故意行为——在这种情况下,您真的不想向stderr 报告。

标准库不会向stderr 报告,所有此类输出都必须显式编码。如果出现诸如 seg-fault 之类的致命错误,您的操作系统可能会向stderr 报告,但这是真正的系统错误,而不仅仅是正常和必需的行为。

【讨论】:

  • 好点。一个程序实际上可以检查一个文件是否存在以及我是否可以打开它(或者它是否存在或者我不能打开它!)而不依赖于特定的实现,通过尝试打开它。 ..
  • 至少在手册页中它被定义为错误Upon successful completion fopen(), fdopen() and freopen() return a FILE pointer. Otherwise, NULL is returned and errno is set to indicate the error.,只要它返回NULL就被认为是错误
  • @mzoz 如果返回 NULL,则表示不成功。我们没有人说别的。这不是系统错误。我们在这里争论语义,关键是通过设置 errno 以外的任何方式报告条件都是错误的。
【解决方案2】:

出现错误时,系统和/或库调用不会自动打印消息。这取决于你。这些函数的作用是返回一个特定的值来指示错误,并设置errno 来指示特定的错误。然后可以使用perror打印出errno当前值对应的错误字符串。

对于fopen,如果调用失败则返回NULL。所以你需要检查它是否这样做,如果是,请使用perror 打印消息。

FILE *fd = fopen("nothing", "r");
if (fd == NULL) {
    perror("fopen failed");
}

以这种方式做事可以让您更好地控制您的程序。例如,在某些情况下,您可能希望文件存在,因此无法打开文件并不是错误,因此在这种情况下您不想打印错误。

【讨论】:

  • 谢谢伙计,你能多回答我添加的问题吗?
  • @mzoz C 没有异常处理,所以没有什么自动的。
  • 那么perror()是触发stderr写作的唯一途径吗?
  • @mzoz 那或使用fprintf(stderr, ...)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多