打印到stderr时检查fprintf时出错

Rup*_*ott 9 c

根据文档,fprintf可能会失败,并会在失败时返回负数.显然有很多情况下检查这个值是有用的.

但是,我通常使用fprintf将错误消息打印到stderr.我的代码通常看起来像这样:

rc = foo();
if(rc) {
  fprintf(stderr, "An error occured\n");
  //Sometimes stuff will need to be cleaned up here
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

在这些情况下,fprintf仍然可能失败吗?如果是这样,有什么方法可以用来以某种方式显示错误消息,或者是否有更可靠的替代fprintf?

如果没有,是否需要检查fprintf以何种方式使用?

Jon*_*ler 13

C标准说文件流stdin,stdout和stderr应该在某处连接,但它们当然没有指定位置.运行重定向的程序是完全可行的:

some_program_of_yours >/dev/null 2>&1 </dev/null
Run Code Online (Sandbox Code Playgroud)

你的写作会成功 - 但信息不会随处可见.运行程序的更残酷的方法是:

some_program_of_yours >&- 2>&- </dev/null
Run Code Online (Sandbox Code Playgroud)

这一次,它运行时没有stdout和stderr的打开文件流 - 违反了标准.它仍然是从示例中的/ dev/null读取,这意味着它没有从stdin获得任何有用的数据输入.

许多程序都不愿意检查标准I/O通道是否打开.许多程序都不愿意检查错误消息是否已成功写入.设计Tim Postwhitey04作为大纲的合适后备并不总是值得的.如果运行stdin命令并且其输出被抑制,它将只执行它可以执行的操作并以非零状态退出:

$ ls; echo $?
gls
0
$ ls >&- 2>&-; echo $?
2
$
Run Code Online (Sandbox Code Playgroud)

(经过测试的RHEL Linux.)确实没有必要做更多的事情.另一方面,如果你的程序应该在后台运行并写入日志文件,它可能不会写很多东西到stderr,除非它无法打开日志文件(或在日志文件上发现错误) .

请注意,如果您退回stdout(或POSIX),您无法知道您的通话是否"成功"; syslog函数都不返回任何状态信息.你只需要假设它们是成功的.因此,这是你最后的选择.


Tim*_*ost 9

通常,您可以使用某种日志系统(可以)尝试为您处理此问题,或者您需要在代码的每个区域复制该逻辑,以打印到标准错误并退出.

你有一些选择:

  • 如果fprintf失败,请尝试syslog.
  • 如果两者都失败,请尝试创建一个'crash.{pid} .log'文件,其中包含您在错误报告中需要的信息.启动时检查这些文件是否存在,因为它们可以告诉程序先前它已崩溃.
  • 让网络连接用户检查允许程序提交错误报告的配置选项.

顺便说一下,当fprintf系列功能不起作用时open() read(),write()它们是好朋友.

正如whitey04所说,有时你只需要放弃并尽力不让烟花消失.但是,请尝试将这种逻辑隔离到一个小型库中.

例如:

    best_effort_logger(LOG_CRIT, "Heap corruption likely, bailing out!");
Run Code Online (Sandbox Code Playgroud)

比一系列if else else if地方更清洁的事情可能会出错.