当std :: fprintf(stderr,...)失败时,操作是否无效或者在失败之前可以写一点?

Dan*_*iel 12 c++ printf c++11

我有一个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)?

fra*_*ian 6

请记住,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)?

这真的取决于你的程序.


Sha*_*our 6

对于fprintfC++ 11标准,可以追溯到C99,因为它是C标准库的一部分,C99草案标准如下:

fprintf函数返回传输的字符数,如果发生输出或编码错误,则返回负值.

但实际上并未指定错误是否表示没有传输任何字符,因此最终将依赖于实现.

对于POSIX兼容系统,在本例中应该涵盖Linux,fprintf参考说:

成功完成后,fprintf()和printf()函数将返回传输的字节数.

[...]

如果遇到输出错误,这些函数将返回负值.

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

[ENOMEM]

存储空间不足.

错误是否表明您应该退出应用程序取决于您的应用程序,您是否有其他备用日志记录机制stderr?您的应用程序是否具有法律要求,要求记录所有内容,或者日志纯粹是信息性的等等......