文件流tellg / tellp和gcc-4.6这是一个bug吗?

时间:2011-07-01 20:23:56

标签: c++ gcc iostream

此代码:

#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&lt; gcc-4.6中的错误)
  3. 两种情况都是正确的,行为未定义

3 个答案:

答案 0 :(得分:5)

好吧,这不是一个错误,即使它似乎是必需的行为:

根据C ++ 2003标准:

  • tellg():( 27.6.1.3)

      

    构造一个sentry对象后,如果fail()!= false,则返回pos_type(-1)表示失败。否则,返回rdbuf() - &gt; pubseekoff(0,cur,in)。

  • 哨兵(27.6.1.1.2):

      

    如果noskipws为零且is.flags()&amp; ios_base :: skipws非零,函数   只要下一个可用输入字符c是空白字符,每个字符就会提取并丢弃它们。如果is.rdbuf() - &gt; sbumpc()或is.rdbuf() - &gt; sgetc()返回traits :: eof(),则函数调用setstate(failbit | eofbit)(可能会抛出ios_base :: failure)

所以基本上

  • tellg()创建哨兵对象:
  • 哨兵提取白色空格字符,并应在进入eof后设置failbit。
  • tellg()看到failbit应该返回eof()( - 1)

所以gcc-4.6似乎行为正确......

答案 1 :(得分:2)

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

它不依赖于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

真正的区别似乎是

  • meerkat:libstdc ++ 6 4.5.1-7ubuntu2
  • natty:libstdc ++ 6 4.6.0-3~ppa1(来自here

关于ubuntu meerkat

$ 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

答案 2 :(得分:2)

好的,与版本分析分开,我将留下一个好的衡量标准,这就是答案:

PR / 26211

我将尝试查找源代码,但此主题讨论了由于此更改是否需要更新文档。因此,记录在案的变更:)

修改只找到了这个:libstdc++/26211 (again) + N3168

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

  嘿,所有。

     

我最近开始使用gcc-4.6.0而且似乎是行为了   当(仅)设置eofbit时,std :: istream :: tellg()已更改。一世   设法追踪到PR / 26211,我没有辩论   变化。

     

我花了一段时间才弄清楚出了什么问题,因为它已经过氧化了   对于tellg()说:

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

Langer和Kreft说的几乎一字不差,所以我就是   假设DR60改为27.6.1.3第37段导致了这一点   改变libstdc ++行为。

     

是否应该更新libstdc ++ doxygen来说明   事实上,tellg()eof()也会返回pos_type(-1)   (因为它构造了一个哨兵)?还有其他吗?   功能也应该有更新的文档作为结果   DR60?