【问题标题】:changing file content - is this a bug in g++ 4.7.2 or am I doing it wrong?更改文件内容 - 这是 g++ 4.7.2 中的错误还是我做错了?
【发布时间】:2016-10-06 17:16:15
【问题描述】:

在编写一些代码来更新二进制文件中的位置时,我注意到了一些奇怪的事情。考虑这个示例代码:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    char tmp;
    string s;
    fstream fs;

    fs.open("test.txt", fstream::out);
    fs << "blub" << endl;
    fs.close();
    fs.open("test.txt", fstream::in);
    fs >> s;
    cout << s << endl;
    fs.close();

    fs.open("test.txt", ios::in|ios::out|ios::binary);
    if (!fs.is_open() || !fs.good())
        cerr << "could not open!" << endl;

    fs.read(&tmp, 1);
    fs.read(&tmp, 1);
    //fs.tellg(); //<-- required to fix for old g++?
    const char *c = "ah";
    fs.write(&c[0], 1);
    fs.write(&c[1], 1);
    fs.close();

    fs.open("test.txt", fstream::in);
    fs >> s;
    cout << s << endl;
}

在最近的 g++ 版本中(至少在 6.2.1 中),我可以毫无问题地读取然后写入一些字节 - 在示例中您会得到正确的输出:

blub
blah

然后我用g++ 4.7.2编译代码,突然更新没有效果,即第二个输出还是“blub”,除非我加fs.tellg()或者fs.tellp ()。我找到了this 的问题,但据我所知,这是 Windows 下的限制,但我在 Linux 下工作。

现在我想知道,这是旧 g++ 中的一个错误,还是我做错了,只是幸运地使用了现代 g++ 版本,它在哪里工作?第二个问题,为什么要求当前位置可以解决问题?

提前致谢!

【问题讨论】:

  • 您链接的答案说您正在做的事情不符合标准,所以是的,您很幸运旧版本的 gcc 不符合标准,但现在看来是。
  • 可能你的意思是反过来?因为它在最近的 g++ 中工作并且在旧版本中被破坏,但如果它不应该工作,这是否意味着新版本符合 LESS 标准?这对我来说没有意义。
  • @apirgov:对不起,我把你说的版本弄混了。是的,听起来新版本违反了标准。
  • C++14 (n4140) 中关于这个主题的标准没有改变。 § 27.9.1.1 /2 规定“读写由类 basic_filebuf 的对象控制的序列的限制与使用标准 C 库文件读写的限制相同。”
  • 所以我认为这实际上是您链接的答案的重复。 gcc 有一个 bug,你应该提交一个 bug 报告。

标签: c++ c++11


【解决方案1】:

现在我想知道,这是旧 g++ 中的错误

没有,g++ 没有这方面的 bug。

还是我做错了

是的。这在您链接的answer 中有说明。

...在没有对 fflush 函数或文件定位函数(fseek、fsetpos 或 rewind)的干预调用的情况下,输出不应直接跟随输入,并且在没有干预调用的情况下,输入不应直接跟随输出到文件定位函数,除非输入操作遇到文件尾。

这来自 C 标准,但通过以下方式相关:

basic_filebuf 类对象控制的序列的读写限制与标准 C 库 FILE 的读写限制相同。

有一个错误,但它在您的代码中。您的程序不符合标准规定的要求。

但据我了解,这是 Windows 下的限制

可能是这样,但更普遍的限制是在 C++(和 C)规范中。标准库是否有限制对库是否符合标准没有影响。任何依赖不存在限制的代码都不符合标准。

并且 [我] 幸运地使用了现代 g++ 版本

有人可能会说你不走运。当程序无法运行并且您发现了错误时,这是​​幸运的。

第二个问题,为什么要求当前位置可以解决问题?

我怀疑tellg 是否足以使您的程序符合标准。所以,我会说它偶然“修复”了程序。

您可能应该改用std::flush(fs);

这是否意味着新版本符合 LESS 标准?

不,这两个版本的 g++ 在这方面同样兼容。你的程序不是。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多