Вопрос
Мне было интересно, в чем смысл засорения?Насколько я могу судить, clog - это то же самое, что cerr, но с буферизацией, поэтому он более эффективен.Обычно stderr - это то же самое, что и stdout, поэтому clog - это то же самое, что cout.Мне это кажется довольно неубедительным, поэтому я полагаю, что, должно быть, неправильно понял.Если у меня есть сообщения журнала, отправляющиеся в то же место, куда у меня отправляются сообщения об ошибках (возможно, что-то в /var/log/messages), то я, вероятно, не записываю слишком много (так что при использовании небуферизованного cerr теряется не так много).По моему опыту, я хочу, чтобы мои сообщения журнала были актуальными (не буферизованными), чтобы я мог помочь найти сбой (поэтому я не хочу использовать буферизованный clog).Очевидно, я всегда должен использовать cerr.
Я хотел бы иметь возможность перенаправлять clog внутри моей программы.Было бы полезно перенаправить cerr, чтобы при вызове библиотечной процедуры я мог контролировать, куда переходят cerr и clog.Могут ли некоторые компиляторы поддерживать это?Я только что проверил DJGPP, и stdout определяется как адрес ФАЙЛОВОЙ структуры, поэтому незаконно делать что-то вроде "stdout = freopen(...)".
- Можно ли перенаправить clog, cerr, cout, stdin, stdout и / или stderr?
- Является ли единственная разница между clog и cerr буферизацией?
- Как мне реализовать (или найти) более надежное средство ведения журнала (ссылки, пожалуйста)?
Решение
Можно ли перенаправить clog, cerr, cout, stdin, stdout и / или stderr?
ДА.Вы хотите, чтобы rdbuf
функция.
ofstream ofs("logfile");
cout.rdbuf(ofs.rdbuf());
cout << "Goes to file." << endl;
Является ли единственная разница между clog и cerr буферизацией?
Насколько я знаю, да.
Другие советы
Если вы работаете в среде оболочки posix (я действительно думаю о bash), вы можете перенаправить любой файловый дескриптор на любой другой файловый дескриптор, поэтому для перенаправления вы можете просто:
$ myprogram 2>&5
перенаправить stderr в файл, представленный fd=5.
Редактировать:если подумать, мне больше нравится ответ @Konrad Rudolph о перенаправлении.rdbuf() - более последовательный и переносимый способ сделать это.
Что касается ведения журнала, хорошо...Я начну с библиотеки Boost для всего, что связано с C ++, которой нет в библиотеке std.Узрите: Ускоренное ведение журнала v2
Редактировать:Ведение журнала Boost - это нет часть библиотек Boost;оно было рассмотрено, но не принято.
Редактировать:2 года спустя, еще в мае 2010 года, Boost принял библиотеку ведения журнала, которая теперь называется Boost.Войти.
Конечно, есть альтернативы:
- Log4Cpp (API в стиле log4j для C ++)
- Log4Cxx (API в стиле log4j, спонсируемый Apache)
- Пантеос (несуществующий?в прошлый раз, когда я пытался, мне не удалось создать его на основе последнего компилятора)
- Глог от Google (кончик шляпы @SuperElectric)
Существует также регистратор событий Windows.
И еще пара статей, которые могут оказаться полезными:
Базовый Регистратор
#define myerr(e) {CriticalSectionLocker crit; std::cerr << e << std::endl;}
Используется как myerr("ERR: " << message);
или myerr("WARN: " << message << code << etc);
Это очень эффективно.
Тогда делай:
./programname.exe 2> ./stderr.log
perl parsestderr.pl stderr.log
или просто проанализируйте stderr.log вручную
Я признаю, что это не для чрезвычайно код, критичный к производительности.Но кто все равно это пишет?
Поскольку здесь есть несколько ответов о перенаправлении, я добавлю этот прекрасный драгоценный камень Недавно я наткнулся на статью о перенаправлении:
#include <fstream>
#include <iostream>
class redirecter
{
public:
redirecter(std::ostream & dst, std::ostream & src)
: src(src), sbuf(src.rdbuf(dst.rdbuf())) {}
~redirecter() { src.rdbuf(sbuf); }
private:
std::ostream & src;
std::streambuf * const sbuf;
};
void hello_world()
{
std::cout << "Hello, world!\n";
}
int main()
{
std::ofstream log("hello-world.log");
redirecter redirect(log, std::cout);
hello_world();
return 0;
}
По сути, это класс перенаправления, который позволяет вам перенаправлять любые два потока и восстанавливать его, когда вы закончите.