Поток файла Tellg / Tellp и GCC-4.6 это ошибка? - PullRequest
6 голосов
/ 02 июля 2011

Этот код:

#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. 1-й случай верен (ошибка в gcc-4.6)
  2. 2-й случай правильный (ошибка в gcc
  3. Оба случая верны, поведение не определено

Ответы [ 3 ]

5 голосов
/ 03 июля 2011

Хорошо, это не ошибка, даже кажется, что требуется поведение:

Согласно стандарту C ++ 2003:

  • tellg (): (27.6.1.3)

    После создания объекта sentry, если fail ()! = False, возвращает pos_type (-1) для обозначения сбоя. В противном случае возвращает rdbuf () -> pubseekoff (0, cur, in).

  • часовой (27.6.1.1.2):

    если noskipws равен нулю и is.flags () & ios_base :: skipws отличен от нуля, функция tion извлекает и отбрасывает каждый символ, если следующий доступный входной символ c является символом пробела. Если is. 1018 *

Так в основном

  • tellg () создает часовой объект:
  • часовой извлекает символы пробела и должен установить failbit после получения eof.
  • tellg () видит, что failbit должен возвращать eof () (-1)

Так что, похоже, gcc-4.6 ведет себя правильно ...

2 голосов
/ 02 июля 2011

Хорошо, отдельно от анализа версий, который я оставлю для хорошей меры, вот ответ:

PR / 26211

Я попытаюсь найти источник, но этот поток обсуждает, нужно ли обновлять документацию из-за этого изменения. Следовательно, это документально подтвержденное изменение:)

Редактировать Только нашел это: libstdc ++ / 26211 (снова) + N3168

С этой страницы: http://gcc.gnu.org/ml/libstdc++/2011-04/msg00026.html

Привет, все.

Я недавно начал использовать gcc-4.6.0, и похоже, что поведение std :: 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 обновится, чтобы что-то сказать о факт, что вызов tellg(), когда eof() также вернет pos_type(-1) (из-за того, что он строит часовой)? Есть ли другие функции, которые также должны иметь обновленную документацию в результате DR60

2 голосов
/ 02 июля 2011

Я могу подтвердить разницу. Однако это не разница компилятора, это не разница заголовков стандартной библиотеки, а разница связанной общей библиотеки.

Это не зависит от версии 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 (из здесь )

На сурикатах Ubuntu

$ 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
...