当std::fprintf(stderr,...)失败时,操作是没有作用还是可以在失败前写一点?

When std::fprintf(stderr,...) fails, does the operation has no effect or can write a little before fail?

我有一个 C++11 程序,它使用 std::fprintf 写入 stderr 作为日志和调试信息。我知道 fprintf 可能会失败并且 return 是一个负值,但我无法找到该操作是否是原子操作(如果失败,则无效)或者它可以写入文本的某些部分然后失败(或任何其他副作用)。

使用 fprintf 的函数如下所示:

void writeToConsole (std::string const &message)
{
    std::fprintf(stderr, "%s\n", message.c_str());
}

我正在 Linux 上使用 Clang 和 GCC 进行开发(目前),但我的问题更多是关于标准的,所以...

问题:

如果std::fprintf失败,是否仍有可能某些字符已写入stderr?此行为是 C/C++ 标准还是实现定义的?

更重要的是,如果 std::fprintf 失败,我应该中止程序还是可以继续静默执行而没有副作用(除了不可能写入 stderr)?

请记住,printf 系列函数(几乎总是)最终会变成 write(2) 函数调用(或其他类似的低级 OS/implementation-provided 等效函数)。这个功能可以部分成功。如果至少写入一个字节,则函数成功(如果未检测到来自底层目标的错误 - 例如,被信号处理程序中断)并且它将return实际写入的字节数:

The number of bytes written may be less than count if, for example, there is insufficient space on the underlying physical medium, or the RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the call was interrupted by a signal handler after having written less than count bytes. [...]

有关部分写入的信息,请参阅 write(2),例如 http://man7.org/linux/man-pages/man2/write.2.htmlerrno 的值或部分写入的其他效果可能取决于输出介质(或文件描述符表示的内容 - 内存映射文件、常规文件等),以及特定的 失败的原因。比如ENOMEM,EIO,EDQUOT都是可能的

另请参阅链接的手册页,了解有关多线程原子性的更多信息。

您的其他问题:

Even more, if std::printf fails, should I abort the program or can continue execution silently without side effects (other than impossibility of write to stderr)?

这真的取决于你的程序。

对于 fprintf,C++11 标准回退到 C99,因为它是 C 标准库的一部分,并且 C99 标准草案规定如下:

The fprintf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred.

但实际上并没有具体说明错误是否意味着没有传输字符,因此最终将取决于实现。

对于 POSIX compliant systems, which in this case should cover Linux, the reference for fprintf 说:

Upon successful completion, the fprintf() and printf() functions shall return the number of bytes transmitted.

[...]

If an output error was encountered, these functions shall return a negative value.

列出了几个可能导致部分输出的错误,例如:

[ENOMEM]

Insufficient storage space is available.

错误是否指示您应该退出您的应用程序取决于您的应用程序,除了 stderr,您是否有替代的日志记录机制?您的应用程序是否有强制记录所有内容的法律要求,或者日志是否纯粹是信息性的,等等...