繁体   English   中英

打印到stderr时检查fprintf时出错

[英]Error checking fprintf when printing to stderr

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

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

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

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

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

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

some_program_of_yours >/dev/null 2>&1 </dev/null

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

some_program_of_yours >&- 2>&- </dev/null

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

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

$ ls; echo $?
gls
0
$ ls >&- 2>&-; echo $?
2
$

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

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

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

你有一些选择:

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

顺便说一下,当fprintf系列函数不工作时, open() read()write()是好朋友。

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

例如:

    best_effort_logger(LOG_CRIT, "Heap corruption likely, bailing out!");

比了一系列更清洁的if else else if每一个地方的东西可能出问题。

你可以将错误放在stdout或其他地方......在某些时候你只需要给出错误报告,然后放弃。

关键是你的应用程序“优雅地”处理它(例如,操作系统不必因为坏而杀死它,它会告诉你为什么退出它[如果它可以])。

是的,当然fprintfstderr可能会失败。 例如, stderr可能是普通文件,磁盘可能空间不足,或者它可能是读取器关闭的管道等。

是否应该检查操作是否失败在很大程度上取决于您是否可以通过检查来实现更好的程序行为。 在你的情况下,你可以做的唯一可以想象的事情是打印错误信息失败是尝试打印另一个(几乎肯定也会失败)或退出程序(这可能比没有报告错误更糟糕,但也许不总是)。

一些真正想要记录错误消息的程序将在程序启动时设置备用堆栈以保留一定量的内存(请参阅信号处理程序(通常为SIGSEGV )可用于报告错误的sigaltstack(2) 。记录你的错误的重要性,你可以调查使用备用堆栈预先分配一些内存。它可能不值得:)但有时你会给出一些事情的暗示

暂无
暂无

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

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