当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.html。 errno
的值或部分写入的其他效果可能取决于输出介质(或文件描述符表示的内容 - 内存映射文件、常规文件等),以及特定的 失败的原因。比如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
,您是否有替代的日志记录机制?您的应用程序是否有强制记录所有内容的法律要求,或者日志是否纯粹是信息性的,等等...
我有一个 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.html。 errno
的值或部分写入的其他效果可能取决于输出介质(或文件描述符表示的内容 - 内存映射文件、常规文件等),以及特定的 失败的原因。比如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
,您是否有替代的日志记录机制?您的应用程序是否有强制记录所有内容的法律要求,或者日志是否纯粹是信息性的,等等...