Какой смысл забивать?

Мне было интересно, какой смысл засорить? Насколько я могу судить, clog аналогичен cerr, но с буферизацией, поэтому он более эффективен. Обычно stderr - это то же самое, что и stdout, поэтому clog аналогичен cout. Мне это кажется очень хромым, поэтому я полагаю, что, должно быть, это неправильно понимаю. Если у меня есть сообщения журнала, выходящие на одно и то же место, у меня появляются сообщения об ошибках (возможно, что-то в /var/log/messages ), тогда я, вероятно, не слишком много пишу (так что не так много потеряно, -буферизованный cerr). По моему опыту, я хочу, чтобы мои сообщения журнала обновлялись (не буферизованы), поэтому я могу помочь найти сбой (поэтому я не хочу использовать буферизованный затвор). По-видимому, я всегда должен использовать cerr.

Я хотел бы иметь возможность перенаправлять глюк внутри моей программы. Было бы полезно перенаправить cerr, чтобы, когда я вызываю библиотечную процедуру, я могу контролировать, где происходит cerr и clog. Могут ли некоторые компиляторы поддержать это? Я просто проверил DJGPP, а stdout определяется как адрес структуры FILE, поэтому незаконно делать что-то вроде "stdout = freopen (...)".

  • Можно ли перенаправить clog, cerr, cout, stdin, stdout и/или stderr?
  • Единственная разница между буферами и cerr буферизацией?
  • Как мне (или найти) более надежное средство ведения журнала (ссылки)?

Ответ 1

Можно ли перенаправить clog, cerr, cout, stdin, stdout и/или stderr?

Да. Вы хотите rdbuf.

ofstream ofs("logfile");
cout.rdbuf(ofs.rdbuf());
cout << "Goes to file." << endl;

Является ли разница между clog и cerr буферизацией?

Насколько я знаю, да.

Ответ 2

Если вы находитесь в среде оболочки posix (я действительно думаю о bash), вы можете перенаправить любые файловый дескриптор для любого другого дескриптора файла, поэтому для перенаправления вы можете просто:

$ myprogram 2>&5 

перенаправить stderr в файл, представленный fd = 5.

Редактировать: на второй мысли мне нравится @Konrad Rudolph, ответьте о перенаправлении лучше. rdbuf() - более последовательный и переносимый способ сделать это.

Что касается ведения журнала, ну... Я начинаю с библиотеки Boost для всех вещей С++, которые не находятся в библиотеке std. Вот: Boost Logging v2

Изменить: Boost Logging не является частью библиотек Boost; он был рассмотрен, но не принят.

Изменить: 2 года спустя, еще в мае 2010 года, Boost принял библиотеку регистрации, теперь называемую Boost.Log.

Конечно, есть альтернативы:

  • Log4Cpp (API-интерфейс типа log4j для С++)
  • Log4Cxx (поддерживаемый Apache API-интерфейс log4j)
  • Pantheios (последнее время я пробовал, я не мог заставить его построить последний компилятор)
  • Google Glog (hat-tip @SuperElectric)

Также есть регистратор событий Windows.

И несколько статей, которые могут быть полезны:

Ответ 3

Основной регистратор

#define myerr(e) {CriticalSectionLocker crit; std::cerr << e << std::endl;}

Используется как myerr("ERR: " << message); или myerr("WARN: " << message << code << etc);

Очень эффективен.

Тогда do:

./programname.exe 2> ./stderr.log
perl parsestderr.pl stderr.log

или просто разобрать stderr.log вручную

Я признаю, что это не для чрезвычайно критического кода производительности. Но кто пишет это в любом случае.

Ответ 4

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

#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;
}

В основном это класс перенаправления, который позволяет вам перенаправлять любые два потока и восстанавливать его, когда вы закончите.