我有一个C++11程序,它使用std::fprintf
写入stderr
作为日志和调试信息。我知道fprintf
可能会失败并返回负值,但我找不到操作是原子的(如果失败,则没有效果)或者它可以写入文本的某些部分然后失败(或任何其他副作用)。
使用 fprintf
的函数如下所示:
void writeToConsole (std::string const &message)
{
std::fprintf(stderr, "%sn", message.c_str());
}
我正在Linux上使用Clang和GCC进行开发(目前),但我的问题更多的是关于标准,所以......
问题:
如果std::fprintf
失败,是否仍有可能将某些字符写入stderr
?这种行为是 C/C++ 标准还是实现定义的?
更重要的是,如果std::fprintf
失败,我应该中止程序还是可以继续静默执行而不会产生副作用(除了无法写入stderr
)?
,printf
系列函数(几乎总是)最终会变成write(2)
函数调用(或其他此类低级,OS/实现提供的等效项)。 此函数可以部分成功。如果至少写入了一个字节,则该函数成功(如果无法检测到来自基础目标的错误 - 例如,信号处理程序中断),它将返回实际写入的字节数:
写入的字节数可能小于计数,例如,如果底层物理介质上的空间不足,或者遇到RLIMIT_FSIZE资源限制(参见setrlimit(2)),或者调用在写入小于计数字节后被信号处理程序中断。 [...]
有关部分写入的信息,请参阅 write(2)
,例如在 http://man7.org/linux/man-pages/man2/write.2.html。 部分写入的errno
或其他效果的值可能取决于输出介质(或文件描述符表示的内容 - 内存映射文件、常规文件等),以及失败的具体原因。 例如,ENOMEM,
EIO,
EDQUOT
都是可能性。
另请参阅链接的手册页,了解有关多线程原子性的更多信息。
您的另一个问题:
更重要的是,如果 std::p rintf 失败,我应该中止程序还是可以继续静默执行而不会产生副作用(除了无法写入 stderr)?
这实际上取决于您的程序。
对于fprintf
,C++11标准回退到C99,因为它是C标准库的一部分,C99草案标准如下:
fprintf 函数返回传输的字符数,或 如果发生输出或编码错误,则为负值。
但实际上并没有指定错误是否意味着没有传输字符,因此最终将取决于实现。
对于POSIX兼容的系统,在这种情况下应该涵盖Linux,fprintf的参考资料说:
成功完成后,fprintf() 和 printf() 函数应返回传输的字节数。
[...]
如果遇到输出错误,这些函数应返回负值。
列出了几个可能导致部分输出的错误,例如:
[恩诺姆]
可用的存储空间不足。
错误是否指示应退出应用程序取决于您的应用程序,您是否有除stderr
之外的备用日志记录机制?您的应用程序是否有法律要求强制记录所有内容,或者日志是否纯粹是信息性的,等等......