为什么C ++标准会处理文件查找方式?


17

C ++使用该streamoff类型表示(文件)流中的偏移量,并在[stream.types]中定义如下:

using streamoff = implementation-defined ;

类型streamoff是已签名的基本整数类型之一的同义词,该基本整数类型的大小足以表示操作系统的最大可能文件大小。287)

287)通常很长很长。

这是有道理的,因为它允许在大型文件中进行查找(与使用相比long,后者可能只有32位宽)。

[filebuf.virtuals]定义了basic_filebuf在文件中进行搜索的功能,如下所示:

pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;

off_type等价于streamoff,请参见[iostreams.limits.pos]。但是,该标准随后继续说明了该功能的作用。最后一句话让我很生气,这需要调用fseek

效果width表示a_codecvt.encoding()。如果is_open() == false是或off != 0 && width <= 0,则定位操作将失败。否则,如果way != basic_ios::curoff != 0,并且输出了最后一个操作,则更新输出序列并写入所有未移位序列。接下来,寻找新的位置:if width > 0,请致电fseek(file, width * off, whence),否则请致电fseek(file, 0, whence)

fseek接受long参数。如果off_typestreamoff被定义为long long(如标准所建议),则可能导致向下转换为long调用时fseek(file, width * off, whence)(导致可能难以诊断的错误)。这使人们质疑streamoff首先引入该类型的全部理由。

这是故意的还是标准的缺陷?


8
缺陷看起来像。
Yakk-Adam Nevraumont

我想我看到gcc libstdc ++使用了fseeko64
KamilCuk

1
临时而言,它看起来seekoff不一定必须在引擎盖下使用 fseek。而是,(大概很熟悉?)的行为fseek用来解释seekoff正在做什么。
jjramsey

@jjramsey这也是我的印象。但是,措辞的方式似乎暗示了一种要求而不是一种解释。
jceed2

1
@jjramsey我同意可以将“效果”部分合理地解释为意味着fseek只要它执行具有相同效果的操作,它实际上就不必调用。但是fseek,如果偏移量小于LONG_MIN或大于LONG_MAX无效,则说明至多是不完整的,至少对于streamoff宽于的实现而言long
基思·汤普森

Answers:


6

我认为您从中得出的结论是C ++流之间不匹配,fseek这将导致运行时错误,这是不正确的。情况似乎是:

  1. long64位的系统上,streamoff定义为long,并且seekoff函数调用fseek

  2. long32位但OS支持64位文件偏移量的系统上,streamoff被定义为long longseekoff调用一个称为fseeko或的函数,该函数fseeko64接受64位偏移量。

这是seekoff我的Linux系统上的定义的摘录:

#ifdef _GLIBCXX_USE_LFS
    if (!fseeko64(_M_file, __off, __whence))
      __ret = std::streampos(ftello64(_M_file));
#else
    if (!fseek(_M_file, __off, __whence))
      __ret = std::streampos(std::ftell(_M_file));
#endif

LFS代表大文件支持

结论:虽然该标准提出了streamoff表面上与seekoffinvoke 要求相冲突的定义fseek,但库设计人员理解,他们必须调用fseekOS 的变体,以接受OS支持的所有偏移量。


@ypnos我没有投票,我觉得这个答案有用。我猜有人投票否决了,因为它没有讲到重点。问题不是在这方面有理智的实现忽略了该标准,而是问题是该理智需要忽略该标准。
jceed2

6
The situation seems to be:-的情况是,实施不允许不叫fseekseekoff。它必须调用fseek,但不是,标准表示必须调用。我可以说这个实现是无效的。我相信它不能回答问题。ch,找到llvm,它调用fseeko
KamilCuk

就像FYI一样,VC ++也需要_fseeki64此函数。这似乎也违反了标准规定。
ChrisMM '19

1
这是实施者意识到问题而忽略标准的情况。我很高兴他们做到了,但是标准确实需要固定。
NathanOliver

1
有些人从字面上看也采用该标准。并不需要实现从字面上调用名为的函数fseek。该标准在其他地方将其描述为“好像通过调用” fseek(...)。如果它非常关心字面量调用fseek,那么该语句将有所不同。认真地说,如果要实现C ++库,该怎么办?fseek因为文档告诉您,您是否要坚持使用64位文件偏移量的低32位进行调用?您的客户会为此感谢您吗?
威利斯·布莱克本
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.