Автор представил этот код под заголовком A bus error on my platform
#include <fstream>
#include <iostream>
int main()
{
std::ofstream log("oops.log");
std::cout.rdbuf(log.rdbuf());
std::cout << "Oops!\n";
return 0;
}
Строка «Oops! \ N» выводится в файл «oops.log». Код не восстанавливает streambuf cout, но VS2010 не сообщил об ошибке во время выполнения.
поскольку log
а также std::cout
поделиться буфером, этот буфер, вероятно, будет освобожден дважды (один раз, когда log
выходит из области видимости, затем еще раз, когда программа завершается).
Это приводит к неопределенному поведению, поэтому трудно сказать точную причину, по которой это вызывает ошибку шины на его компьютере, но на вашем компьютере ничего не происходит.
Поскольку в других ответах не упоминается, что с этим делать, я приведу это здесь. Вам нужно сохранить и восстановить буфер, которым должен управлять cout. Например:
#include <fstream>
#include <iostream>
// RAII method of restoring a buffer
struct buffer_restorer {
std::ios &m_s;
std::streambuf *m_buf;
buffer_restorer(std::ios &s, std::streambuf *buf) : m_s(s), m_buf(buf) {}
~buffer_restorer() { m_s.rdbuf(m_buf); }
};
int main()
{
std::ofstream log("oops.log");
buffer_restorer r(std::cout, std::cout.rdbuf(log.rdbuf()));
std::cout << "Oops!\n";
return 0;
}
Теперь когда cout
буфер заменяется раньше cout
уничтожается в конце программы, поэтому, когда cout
уничтожает свой буфер, происходит правильная вещь.
Для простого перенаправления стандартного ввода-вывода обычно в среде уже есть возможность сделать это за вас (например, перенаправление ввода-вывода в оболочке). Вместо приведенного выше кода я бы, вероятно, просто запустил программу как:
yourprogram > oops.log
Также следует помнить, что std::cout
является глобальной переменной со всеми теми же недостатками, что и другие глобальные переменные. Вместо того, чтобы изменять его или даже использовать его, вы можете предпочесть использовать обычные методы, чтобы избежать глобальных переменных все вместе. Например, вы можете передать std::ostream &log_output
параметр вокруг и использовать его вместо использования кода cout
непосредственно.
Ваша программа имеет неопределенное поведение.
Деструктор глобального cout
объект удалит буфер потока при выходе из области видимости, и то же самое верно для log
, который также владеет тем же буфером потока. Таким образом, вы удаляете один и тот же объект дважды.
Когда программа имеет неопределенное поведение, может произойти все что угодно, от форматирования жесткого диска до завершения без каких-либо ошибок.
На моей платформе, например, программа входит в бесконечный цикл после возвращения из main()
,