当 std::fprintf(stderr,..) 失败时,操作是否不起作用,或者可以在失败之前写入一点



我有一个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之外的备用日志记录机制?您的应用程序是否有法律要求强制记录所有内容,或者日志是否纯粹是信息性的,等等......

相关内容

最新更新