将调试输出重定向到null流,而不是std :: cerr [英] Redirect debug output to null stream instead of std::cerr
问题描述
我正在使用的软件库向 std :: cerr
中写入了大量调试输出,但是如果我告诉它将输出重定向到一个null流安静。这是一个简化的 main.cpp
,显示代码如何尝试实现这一点:
#include< iostream>
#include< fstream>
#include< cassert>
//调试输出的流发送到。默认情况下
//这指向std :: cerr。
std :: ostream * debugStream(& std :: cerr);
//在整个库的代码库中,这个函数被调用
//来获取调试输出应该发送到的流。
std :: ostream& DebugStream()
{
return * debugStream;
}
//空流。此文件流将永远不会打开,并将
//作为DebugStream()的空流。
std :: ofstream nullStream;
//将调试输出重定向到null流
void BeQuiet()
{
debugStream =& nullStream;
}
int main(int argc,char ** argv)
{
DebugStream()< foo< std :: endl;
BeQuiet();
DebugStream()<< bar< std :: endl;
assert(debugStream-> good());
return 0;
}
运行此程序时,您会注意到字符串bar正确发送到零流。然而,我注意到断言失败。这是我应该关心的吗?或者,这只是图书馆开发人员选择的方法的一个略微丑陋的细节?
如果你喜欢它,欢迎提出更好的替代方案。一些约束:
- 库是跨平台的,所以我想使用打开
/ dev / null
不是有效的解决方案,因为它不能在Windows上运行 - 该库使用标准C ++,所以任何替代解决方案不应使用编译器特定的东西
没有真正需要担心的流不是 good / code>!由于输出运算符在失败模式下并不真正做任何流,所以不同的实体不被格式化,即,与其他方法相比,代码运行得更快。
注意,你不需要第二个流来禁用输出:
-
假设所有的输出操作符都是良好的,您只需设置
std :: ios_base :: failbit
:debugStream()。setstate(std :: ios_base :: failbit);
-
如果有错误的输出写入流,即使不是
good()
你可以将它的流缓冲区设置为null:
debugStream()。rdbuf(nullptr) p>
如果您确实希望将流保留在 good()
状态,您将安装一个仅消耗字符的流缓冲区。注意,你想给这个流缓冲区一个缓冲区,因为每个 char
调用 overflow()
相当冒险:
struct nullbuf
:std :: streambuf {
char buf [256]
int overflow(int c){
this-> setp(this-> buf,this-> buf + 256);
return std :: char_traits< char> :: not_eof(c);
}
};
...
nullbuf sbuf;
debuggingStream()。rdbuf(& sbuf);
...
DebugStream()。rdbuf(0);
有必要重置流的流缓冲区,因为 std的析构函数:: ostream
将刷新stresm缓冲区(即,它调用 pubsync()
)。
个人而言,我会设置 std :: ios_base :: failbit
。
A software library that I am working with writes a lot of debug output to std::cerr
, but redirects that output to a null stream if I tell it to be quiet. This is a simplified main.cpp
that shows how the code tries to achieve this:
#include <iostream>
#include <fstream>
#include <cassert>
// The stream that debug output is sent to. By default
// this points to std::cerr.
std::ostream* debugStream(&std::cerr);
// Throughout the library's codebase this function is called
// to get the stream that debug output should be sent to.
std::ostream& DebugStream()
{
return *debugStream;
}
// Null stream. This file stream will never be opened and acts
// as a null stream for DebugStream().
std::ofstream nullStream;
// Redirects debug output to the null stream
void BeQuiet()
{
debugStream = &nullStream;
}
int main(int argc, char** argv)
{
DebugStream() << "foo" << std::endl;
BeQuiet();
DebugStream() << "bar" << std::endl;
assert(debugStream->good());
return 0;
}
When you run this program, you will notice that the string "bar" is correctly sent to the null stream. However, I noticed that the assertion fails. Is this something that I should be concerned about? Or is this just a slightly ugly detail of the approach chosen by the library developers?
If you feel like it, suggestions for better alternatives are welcome. Some constraints:
- The library is cross-platform, so I think using opening
/dev/null
is not a valid solution as it would not work on Windows - The library uses standard C++, so any alternative solutions should not use compiler-specific stuff
There is no real need to be worried about the stream not being good()
! Since the output operators don't really do anything wirh a stream in failure mode the different entities being logged are not formatted, i.e., the code does run faster compared to alternative approaches.
Note that you don't really need a second stream to disable output:
Assuming all output operators are well-behaved, you can just set
std::ios_base::failbit
:debugStream().setstate(std::ios_base::failbit);
If there are misbehaved output which write to a stream even if it isn't
good()
you can just set its stream buffer to null:debugStream().rdbuf(nullptr);
If you really want your stream to remain in good()
state, you'd install a stream buffer which just consumes characters. Note, however, that you want to give this stream buffer a buffer as having overflow()
called for each char
is fairly exensive:
struct nullbuf
: std::streambuf {
char buf[256];
int overflow(int c) {
this->setp(this->buf, this->buf + 256);
return std::char_traits<char>::not_eof(c);
}
};
...
nullbuf sbuf;
debugStream().rdbuf(&sbuf);
...
debugStream().rdbuf(0);
It is necessary to reset the stream's stream buffer because the destructor of an std::ostream
will flush the stresm buffer (i.e., it calls pubsync()
). Doing so on a destroyed stream buffer won't work.
Personally, I would go with setting std::ios_base::failbit
.
这篇关于将调试输出重定向到null流,而不是std :: cerr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!