文件流tellg/tellp和gcc-4.6这是一个错误吗

file stream tellg/tellp and gcc-4.6 is this a bug?

本文关键字:一个 错误 tellg tellp gcc-4 文件      更新时间:2023-10-16

此代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <string>
int main()
{   
    std::remove("test.txt");
    std::fstream f("test.txt",std::ios::in | std::ios::out | std::ios::binary | std::ios::trunc);
    std::cout << f.good() << std::endl;
    f<<"test"<< std::flush;
    std::cout << f.tellg() << " " << f.tellp() << std::endl;
    f.seekg(0);
    std::string s;
    f>>s;
    std::cout << f.tellg() << " " << f.tellp() << std::endl;
}   

在gcc-4.4.5 中给出以下输出

1
4 4
4 4

即tellg和tellp都返回了预期的流位置4。

而gcc-4.6.0

提供:

1
4 4
-1 4

我在哪里可以找到参考资料:

  1. 第一种情况是正确的(gcc-4.6中的错误(
  2. 第二种情况是正确的(gcc<gcc-4.6中的错误(
  3. 两种情况都是正确的行为未定义

好吧,这不是一个bug,即使它看起来是必需的行为:

根据C++2003标准:

  • tellg((:(27.6.1.3(

    构造哨兵对象后,如果失败((!=false,返回pos_type(-1(以指示失败。否则,返回rdbuf((->pubseekoff(0,cur,in(。

  • 哨兵(27.6.1.1.2(:

    如果noskipws为零并且是.flags((&ios_base::skipws为非零,则函数-tion提取并丢弃每个字符,只要下一个可用的输入字符c是空白字符即可。如果is.rdbuf((->sbumpc((或is.rdbub((->sgetc((返回traits::of((,则函数调用setstate(failbit|eofbit((可能引发ios_base::failure(。

所以基本上

  • tellg((创建哨兵对象:
  • sentry提取空白字符,到达eof后应设置failbit
  • tellg((看到故障位应返回eof(((-1(

所以gcc-4.6的行为似乎是正确的。。。

我可以确认差异。然而,不是编译器的区别,不是标准库头的区别,而是链接共享库的区别。

它不依赖于gcc版本。它不依赖于架构:

t44:       ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
t45:       ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
t46:       ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped

真正的区别似乎是

  • 猫鼬:libstdc++6 4.5.1-ubuntu2
  • natty:libstdc++6 4.6.0-3~ppa1(从这里开始(

关于乌班图猫鼬

$ uname -a
Linux natty 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:24 UTC 2011 i686 GNU/Linux
$ for a in t4?; do ./$a; done
1
4 4
4 4
1
4 4
4 4
1
4 4
4 4

关于ubuntu natty

Linux natty 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:24 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
sehe@natty:/mnt/jail/home/sehe$ for a in t4?; do ./$a; done
1
4 4
-1 4
1
4 4
-1 4
1
4 4
-1 4

好的,与版本分析分开,我将把它留作衡量标准,答案是:

PR/26211

我将尝试查找源代码,但本线程讨论了由于此更改是否需要更新文档。因此,这是一个有记录的变化:(

编辑只找到这个:libstdc++/26211(再次(+N3168

从此页面:http://gcc.gnu.org/ml/libstdc++/2011-04/msg00026.html

大家好。

我最近开始使用gcc-4.6.0std::istream::tellg((在设置eofbit时发生了更改。我设法追踪到PR/26211,我没有争论更改。

我花了一段时间才弄清楚出了什么问题,因为for tellg((表示:

If fail() is not false, returns pos_type(-1) to indicate
failure. Otherwise returns rdbuf()->pubseekoff(0,cur,in).

兰格和克雷夫特几乎是逐字逐句地说的,所以我假设DR60对27.6.1.3第37段的修改导致了这种情况libstdc++行为的更改。

是否应该更新libstdc++doxygen来说明在eof()时调用tellg()也将返回pos_type(-1)(因为它建造了一个哨兵(?还有其他的吗由于DR60?

相关文章: