6

If I call a POSIX function like read() that isn't part of the C++ standard library I have to worry about it being interrupted by a signal and handle an EINTR return value. If I call a C++ standard library function like fread() based on this documentation there is no mention of EINTR so it seems like the standard library hides this from the user. Is my understanding correct and does this hold for all C++ standard library functions?

Update: So what is still not clear from the responses is that is the conclusion that one can't write standard C++ that properly functions on every platform? I'm seeing people mention POSIX behavior that is not part of the standard so this is confusing.

4

3 回答 3

3

如果我调用一个read()不属于 C++ 标准库的 POSIX 函数,我不得不担心它会被信号中断并处理EINTR返回值。

这对您的代码来说应该不是问题,因为:

  1. read可能会失败,因此返回值,errno无论如何都必须处理。
  2. read可以进行部分读取,因此在阻塞模式下您必须read循环调用。errno == EINTR只是在阻塞和非阻塞模式下重试调用的另一个条件。
于 2019-06-11T09:43:58.473 回答
1

POSIX也涵盖fread了,这很好,因为 C 和 C++ 标准很少提及支持 POSIX 以外的信号。它说,部分在fgetc页面上,fread可能会提前返回(可能返回 0)、setferror和 set errnoto EINTR。当然,如果信号导致短路read,C 库无法检测到它,它只会read再次调用,因此您不能依赖及时响应信号。写作是类似的。

C++ 标准库中很少有其他操作可以产生EINTR; 不幸的是,POSIX 不涵盖 C++,因此对于 C 中没有的东西没有确定的答案sleep_for

于 2019-06-11T06:46:04.633 回答
0

fread()最初是 C 标准库的一部分libc,定义在<stdio.h>. C++ 标准库fread()通过 C 库包装器提供相同的功能<cstdio>

read()没有这样的包装器(可能是因为它会与istream's 的版本冲突),但您仍然可以使用 C 库调用它。你是对的,它read()来自 POSIX 特定的扩展 <unistd.h>并且不是标准库的一部分,但它已经被广泛地实现并且经常与libc.

您也是正确的,read()它将设置errno为失败,其中一个错误可能是EINTR. 另一方面,当fread()失败时,没有办法找出发生了什么错误,所以从技术上讲,EINTR在这种情况下,用户对用户隐藏事件也是正确的。实际上,如何fread()处理任何特定于平台的细节取决于实现。但是说这种模式适用于“所有 C++ 标准库函数”会有点牵强——你真的必须逐个检查。

如果您想编写在每个平台上运行的“正常运行”的代码,请不要使用 POSIX 扩展。坚持fread()和朋友们,并接受这样一个事实,即跨平台的泛化意味着您可能无法获得平台特定的详细信息,例如错误号。由于可能的错误是特定于平台的,因此没有通用的方法可以知道您是否应该重试。

read()有关和fread()之间差异的更多详细信息,请参见此处

于 2019-06-14T15:10:30.540 回答