Рассмотрим следующий код:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <tuple>
auto read_data(std::ifstream& training_file) {
if (!training_file) {
throw std::runtime_error{"Error: could not open one or more files"};
}
std::stringstream training{};
training << training_file.rdbuf();
std::cout << training.str() << '\n';
return std::tie(training);
}
int main() {
std::ifstream input{"input.txt"};
auto [train] = read_data(input);
std::cout << train.str() << '\n';
std::cout << "x" << '\n';
}
И не обращайте внимания на тот факт, что я возвращаю один элемент с std::tie
(изначально я tie
использую два std::stringstream
объекта, но это не нужнодля MCVE).
Файл input.txt
выглядит следующим образом:
0,0,0,0,
0,0,0,0,
Примечание - после второй строки нет разрыва строки.
Неожиданный вывод этой программы:
0,0,0,0,
0,0,0,0,
É$~ Ź ,
x
Очевидно, что часть É$~ Ź ,
не должна была быть там.
Обратите внимание, что я выводил то же самое содержимое файла.Я не знаю, откуда взялась неожиданная часть.
Становится еще более странным, когда играешь с кодом.Если я закомментирую std::cout << train.str() << '\n';
в main()
и продублирую строку std::cout << training.str() << '\n';
в функции read_data()
, результат будет таким, как ожидалось:
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
x
Так что это не вызываетсяпозвонив std::stringstream::str
дважды.Это должно быть вызвано использованием возвращаемого значения.
Что еще?Выполнение строки std::cout << train.str() << '\n';
из main()
дважды приводит к завершению программы с code 3
.
GDB сообщает:
gdb: unknown target exception 0x80000001 at 0x7ff909e845c0
Thread 1 received signal ?, Unknown signal.
0x00007ff909e845c0 in ?? ()
Но это все жене заканчивается здесь .Если я изменю содержимое файла так, чтобы оно содержало:
0 0
или
0 0 0 0
0 0 0 0
, вывод снова будет таким, как ожидалось (с использованием исходного кода - один cout
в read_data()
иодин в main()
.
Чтобы убедиться, что меня не обманул какой-то непечатаемый символ, проникший в мой файл, я использовал PowerShell для вывода его шестнадцатеричного представления, что привело к следующей последовательности относительноИсходное содержимое файла:
30 20 30 20 30 20 30 0D 0A 30 20 30 20 30 20 30
Как видите, в моем файле нет ничего, кроме 0
s, пробелов и carriage-return + line-feed
.
Есть идеи, почему это может происходить?Для полной информации я использую GCC 8.2.0 от MinGW.