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