В чем смысл засора?

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

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

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

Usually stderr is the same as stdout определенно неверен для Unix и его вариантов. Их можно, например, перенаправить отдельно.

Andre Holzner 31.12.2011 21:47

@AndreHolzner Это также верно во всех средах DOS / Windows, 2> действителен в командной строке Windows 7, например, как способ перенаправления stderr.

Benj 19.10.2012 18:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
58
2
28 492
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Is it possible to redirect clog, cerr, cout, stdin, stdout, and/or stderr?

Да. Вам нужна функция rdbuf.

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

Is the only difference between clog and cerr the buffering?

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

Дополнительную информацию можно найти на stackoverflow.com/questions/33601886/….

R Sahu 09.11.2015 18:48

Закройте и сбросьте cout после записи или получите segfault: ofs.close(); cout.rdbuf(nullptr);

micah94 07.08.2016 05:18

@ micah94 Поток закрывается автоматически в конце области видимости, нет необходимости делать это вручную. Но хороший момент по поводу сброса буфера cout.

Konrad Rudolph 07.08.2016 11:11

Просто проверка: если после того, как вы сделаете этот rdbuf, вы попытаетесь писать в ofs и cout одновременно из двух разных потоков, вы получите гонку данных и неопределенное поведение, верно? (Но это нормально, если вы никогда не пишете через ofs, или если вы явно синхронизируете свои записи с мьютексом или чем-то еще.)

Quuxplusone 11.08.2017 21:39

@Quuxplusone Хороший вопрос. Я не знаю, в какой момент синхронизируются выходные потоки, но вы, вероятно, правы.

Konrad Rudolph 14.08.2017 12:54

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

$ myprogram 2>&5 

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

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

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

Редактировать: ведение журнала ускорения является частью нет библиотек ускорения; он был рассмотрен, но не принят.

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

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

  • Log4Cpp (API в стиле log4j для C++)
  • Log4Cxx (API в стиле log4j, спонсируемый Apache)
  • Пантеиос (несуществующий? В прошлый раз, когда я пытался, я не мог заставить его построить на недавнем компиляторе)
  • Google GLog (шляпа-наконечник @SuperElectric)

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

И пара статей, которые могут пригодиться:

Следует отметить, что «Boost Logging v2» не является частью ускорения, а является предлагаемой библиотекой, которая может быть принята или не принята при рассмотрении.

Adam Mitz 10.09.2008 08:47

Хорошая точка зрения. Библиотека была проверена 2/4 / 2008-2 / 13/2008 и, по-видимому, отклонена. Он может быть пересмотрен повторно. Вероятно, лучше всего подходят log4cxx или log4cpp.

Ben Collins 10.09.2008 17:56

Или используйте простое линейное решение std::cerr.

unixman83 18.12.2010 04:40

Я также настоятельно рекомендую Google GLog (code.google.com/p/google-glog), особенно за его краткие макросы assert с информативными сообщениями об ошибках.

SuperElectric 15.03.2011 20:08

Базовый регистратор

#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 вручную

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

#defines не типизированы, и большинство их использования в C++ не рекомендуется.

Raúl Salinas-Monteagudo 13.10.2015 16:52

определения по-прежнему необходимы, если вы хотите автоматический захват _ФАЙЛ_ и _ЛИНИЯ_, что делает большинство людей.

Spacen Jasset 10.03.2017 02:48

@SpacenJasset Если вы не используете std :: source_location (присутствует в C++ 20 и новее).

Alan 13.02.2021 00:53

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

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

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

RAII FTW !!!!! 11

Pedro Boechat 02.01.2021 21:32

Один маленький момент о классе перенаправителя. Его нужно уничтожить как следует, и только один раз. Деструктор гарантирует, что это произойдет, если функция, в которой он объявлен, действительно возвращается, а сам объект никогда не копируется.

Чтобы гарантировать невозможность копирования, укажите операторы частного копирования и присваивания:

class redirecter
{
public:
    redirecter(std::ostream & src, std::ostream & dst)
        : src_(src), sbuf(src.rdbuf(dst.rdbuf())) {}
    ~redirecter() { src.rdbuf(sbuf); }
private:
    std::ostream & src_;
    std::streambuf * const sbuf_;
    // Prevent copying.                        
    redirecter( const redirecter& );
    redirecter& operator=( const redirecter& );
};

Я использую эту технику, перенаправляя std :: clog в файл журнала в main (). Чтобы гарантировать, что main () действительно вернется, я помещаю внутренности main () в блок try / catch. Затем в другом месте моей программы, где я мог бы вызвать exit (), вместо этого я генерирую исключение. Это возвращает управление в main (), которая затем может выполнить оператор return.

Разве стандарт C++ не предпочитает =delete вместо частных конструкторов?

Dynamic Squid 07.11.2020 20:41

@DynamicSquid Я не уверен, что предпочитает стандарт как таковой, но это вещь. Однако OP и / или ответчик должны использовать C++ 11 или новее (что, я думаю, большинство людей сейчас использует).

user10957435 08.11.2020 05:05

Другие вопросы по теме