ERANGE 和 EOVERFLOW 之间的语义区别是啥?

Posted

技术标签:

【中文标题】ERANGE 和 EOVERFLOW 之间的语义区别是啥?【英文标题】:What's the semantic difference between ERANGE and EOVERFLOW?ERANGE 和 EOVERFLOW 之间的语义区别是什么? 【发布时间】:2016-05-01 01:59:01 【问题描述】:

POSIX 将 errnoERANGE 记录为

结果太大。

EOVERFLOW 记录为

值太大而无法存储在数据类型中。

这两者之间的语义区别是什么?特别是考虑到ERANGE 被 ISO 9899 使用(例如在strtol 中),其语义为EOVERFLOW 描述。这两个errno 值是否仅因历史原因而不同?

如果可能,请用适当的来源备份您的论点。

【问题讨论】:

建议使用“EOVERFLOW 被记录为 ...”来回报适当来源的青睐,因为在 C11 规范中 ERANGEEOVERFLOW 不是。 @chux 这就是为什么我说“由 POSIX 记录为”。具体页面为errno.h。 ISO 9899 没有记录ERANGE 的含义。 我明白了 - 最初没有“按 POSIX”阅读以适用于第二行。 - 阅读您发布/评论的内容当然是有意义的。 【参考方案1】:

SingleUnix 关于EOVERFLOW 相当冗长:

值太大而无法存储在数据类型中 IPC 或文件系统对象的用户 ID 或组 ID 太大而无法存储到调用方提供的结构的适当成员中。此错误只会发生在支持的用户 ID 或组 ID 值范围比声明的结构成员可以支持的范围更大的实现上。这通常是因为 IPC 或文件系统对象驻留在远程计算机上,其 uid_t、off_t 或 gid_t 类型的值比本地系统大。

EOVERFLOW 似乎是为了表示子系统不兼容,即某个系统返回的值大于另一个子系统可以处理的值。

EOVERFLOW 的基本原理是 explained in more detail:

此错误代码的大部分用途都与大文件支持有关。通常,这些情况发生在支持具有不同大小的 off_t 的多个编程环境的系统上,但它们也可能与远程文件系统相关。

另外,当不同的编程环境对int、uid_t等类型有不同的宽度时,几个函数可能会遇到特定环境中的值太宽而无法表示的情况。在这种情况下,应该提出这个错误。例如,假设当前运行的进程具有 64 位 int,并且文件描述符 9223372036854775807 是打开的并且没有设置 close-on-exec 标志。如果该进程随后使用 execl() 执行在具有 32 位 int 的编程环境中编译的文件,则对 execl() 的调用可能会失败,并且 errno 设置为 [EOVERFLOW]。如果要分配给新进程映像的任何用户 ID 或任何组 ID 超出已执行文件的编程环境的范围,则 execl() 可能会发生类似的故障。

但是请注意,对于明确描述为始终成功的函数(例如 getpid()),不会发生这种情况。

感谢@rici 的指点

ERANGE 更像是这永远不适合strtol() 就是一个例子。另一个不太清楚的问题:尝试将 SYSV 信号量增加到超过其配置的限制会返回 ERANGE

有了EOVERFLOW 那里的数据,它只是不适合本地数据结构。

例如,lseek() 可以返回 EOVERFLOW。发生这种情况,例如当off_t 仅为 32 位但文件系统可以支持更大的文件并且您尝试寻找超出操作系统可以处理的范围时。为什么不是ERANGE?因为系统原则上可以处理操作,只是不能以可用的数据类型返回给你。

在 Linux 上的 32 位系统上尝试使用 mmap() 映射超过 2G 会返回 EOVERFLOW(其他系统返回 EINVAL)。

不幸的是,这并不完全一致。例如,蓝牙堆栈在发现系统中的主机控制器过多时返回EOVERFLOW

【讨论】:

基本原理(pubs.opengroup.org/onlinepubs/9699919799/xrat/…)中还有更多解释,其中还指出添加了错误ERANGE,因为它用于C标准。 64 位可执行文件execl 一个具有未封闭超出范围 fd 的 32 位二进制文​​件的基本原理中的示例令人着迷。我不知道这是否会发生。 @rici 感谢您的参考,我会添加报价 @rici 这个例子本身有点荒谬,但可以而且确实发生的事情是人们试图在仅实现大文件的系统上执行一个带有打开文件描述符的 32 位程序到一个大文件64 位程序。【参考方案2】:

语义上有区别:

EOVERFLOW 用于缓冲区大小 os 太小并且请求的数据传输会溢出目标缓冲区或类似错误情况的情况:

http://man7.org/linux/man-pages/man2/open_by_handle_at.2.html

EOVERFLOW

         The handle->handle_bytes value passed into the call was too
          small.  When this error occurs, handle->handle_bytes is
          updated to indicate the required size for the handle.

http://man7.org/linux/man-pages/man2/open.2.html

EOVERFLOW

         pathname refers to a regular file that is too large to be
          opened.  The usual scenario here is that an application
          compiled on a 32-bit platform without -D_FILE_OFFSET_BITS=64
          tried to open a file whose size exceeds (1<<31)-1 bytes; see
          also O_LARGEFILE above.  This is the error specified by
          POSIX.1; in kernels before 2.6.24, Linux gave the error EFBIG
          for this case.

ERANGE 用于不适合目标类型 (C99) 的值和超出特定命令定义范围的参数 (POSIX)

但它也用于EOVERFLOW 更合适的错误:

http://man7.org/linux/man-pages/man3/pthread_setname_np.3.html

  The pthread_setname_np() function can fail with the following error:

 ERANGE The length of the string specified pointed to by name exceeds
          the allowed limit.

  The pthread_getname_np() function can fail with the following error:

  ERANGE The buffer specified by name and len is too small to hold the
          thread name.

我猜EOVERFLOW 用于系统调用,ERANGE 用于 C 库函数,标准函数和非标准函数。

【讨论】:

以上是关于ERANGE 和 EOVERFLOW 之间的语义区别是啥?的主要内容,如果未能解决你的问题,请参考以下文章

java内存模型之二

属性和字段之间的语义差异及其含义

查找不同单词之间的语义相似性和关系

“查找”和“搜索”之间的语义区别?

如何度量两个词之间的语义相似度

保存/写入/存储和读取/加载之间的语义差异?