如果我调用不属于C ++标准库的read()
之类的POSIX函数,则必须担心它会被信号中断并处理EINTR
返回值。如果我基于this documentation调用诸如fread()
之类的C ++标准库函数,则不会提及EINTR
,因此标准库似乎对用户隐藏了此内容。我的理解正确吗,这是否适用于所有C ++标准库函数?
更新:因此,从响应中仍然不清楚的结论是,人们不能编写在每个平台上都能正常运行的标准C ++?我看到人们提到POSIX行为不是该标准的一部分,所以这很令人困惑。
答案 0 :(得分:3)
如果我调用不属于C ++标准库的
read()
之类的POSIX函数,则必须担心它会被信号中断并处理EINTR
返回值。
这对您的代码来说不是问题,因为:
read
可能会失败,因此无论如何都必须处理返回值和errno
。read
可以进行部分读取,因此在阻塞模式下,您必须循环调用read
。 errno == EINTR
只是在阻塞和非阻塞模式下重试呼叫的另一条件。 答案 1 :(得分:1)
POSIX covers fread
也是很好的,因为C和C ++标准很少说明支持POSIX以外的信号。它说,在fgetc
页面的一部分上,fread
可能会提前返回(可能返回0),设置ferror
,并将errno
设置为EINTR
。当然,如果信号导致短read
,则C库无法检测到该信号,它将再次调用read
,因此您不能依赖于响应及时的时尚。写作是类似的。
C ++标准库中很少有其他操作可以产生EINTR
;不幸的是,POSIX并未涵盖C ++,因此对于sleep_for
之类的不在C中的事物,尚无定论。
答案 2 :(得分:0)
fread()
最初是libc
中定义的C标准库<stdio.h>
的一部分。 C ++标准库通过C库包装器fread()
使相同的<cstdio>
可用。
read()
没有这样的包装器(也许是因为它会与istream
的版本冲突),但是您仍然可以使用C库来调用它。您是正确的,read()
来自特定于POSIX的extension <unistd.h>
,它不是标准库的一部分,但是此后已被广泛实现,并且经常与{{1}一起分发}。
您还纠正了libc
会在失败时设置read()
的情况,并且其中一个错误可能是errno
。另一方面,当EINTR
失败时,可以使用no way来找出发生了什么错误,因此从技术上讲,您还纠正了在这种情况下fread()
对用户隐藏的情况。实际上,EINTR
如何处理任何平台特定的细节取决于实现。但是,要说这种模式适用于“所有C ++标准库函数”,您可能会感到有些牵强-您真的必须视情况进行检查。
如果要编写在每个平台上运行的“功能正常”的代码,请不要使用POSIX扩展。坚守fread()
和朋友,接受一个事实,即跨平台的泛化意味着您可能无法获得特定于平台的详细信息,例如错误号。由于可能的错误是特定于平台的,因此无法通过通用方法知道是否应该重试。
here是fread()
和read()
之间差异的更多详细信息。