使用流在C++中记录信息
using stream to log information in C++
我有一个C++类,它将消息记录到std::ofstream
。 在类定义中是以下代码:
#ifdef NDEBUG
#define FOO_LOG(msg) /* calls to log messages are no-op in release mode */
#else
std::ofstream log_stream;
#define FOO_LOG(msg) if (log_stream.is_open()) { log_stream << msg << std::endl; }
#endif
该类的构造函数需要检查一些内容,在某些情况下将打开类似于以下内容的日志文件:
#ifndef NDEBUG
log_stream.open("output.log");
#endif
然后在代码中,它像这样调用 C 宏:
FOO_LOG("stuff=" << stuff << " in loop counter #" << xyz)
您可以将多个参数传递给FOO_LOG()
宏很方便。 存在明显的限制,例如记录来自多个线程的消息时,但这仅用于调试版本中的简单日志记录。
我想知道的是是否有不同/更好的方法来处理C++中的msg
参数?有没有更简单/更干净的方法来实现类似于C++FOO_LOG()
的东西?
与其在代码中随处#ifdef NDEBUG
,不如在标头的开头有一个#ifdef NDEBUG
来定义其他有用的宏。
对我来说FOO_LOG("stuff=" << stuff << " in loop counter #" << xyz);
感觉有点不自然。我将不得不不断参考宏定义以查看它是如何实现的。相反,您可以定义一个宏以充当std::ostream
,并像使用任何其他流一样使用它。这样你就可以做一些事情,比如LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;
.
对于这个答案,我从这个问题中得到了一些启发。
#include <fstream>
#define NDEBUG
//An ostream class that does nothing
class DummyStream : public std::ostream {
public:
int overflow(int c) { return c; }
} dummyStream;
//Here we let NDEBUG define other macros.
#ifdef NDEBUG
std::ofstream logStream;
std::ostream& oLogStream(*(std::ostream*)&logStream);
#define LOG_STREAM (logStream.is_open() ? oLogStream : dummyStream)
#define OPEN_LOG(log) (logStream.is_open() ? logStream.close(), logStream.open(log, std::ofstream::out | std::ofstream::app) :
logStream.open(log, std::ofstream::out | std::ofstream::app))
#define CLOSE_LOG() (logStream.close())
#else
#define LOG_STREAM (dummyStream)
#define OPEN_LOG(log) //no-op
#define CLOSE_LOG() //no-op
#endif // NDEBUG
int main(int argc, char* argv[]) {
//will only log if NDEBUG is defined.
OPEN_LOG("log.txt");
std::string stuff("stuff to log");
for(int xyz = 0; xyz < 4; xyz++) {
LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;
}
CLOSE_LOG();
//Log is not open so it will not log anything.
stuff = "stuff to not log";
for(int xyz = 0; xyz < 4; xyz++) {
LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;
}
return 0;
}
这有什么好处?
LOG_STREAM
像任何其他流一样更直观地处理。OPEN_LOG(log)
将在打开新日志之前关闭已经打开的日志,当未定义 NDEBUG 时,它将不执行任何操作。CLOSE_LOG()
将关闭日志,当未定义 NDEBUG 时,它将不执行任何操作。- 不需要到处键入
#ifdef NDEBUG ... #endif
。 dummyStream
可以用std::cout
或其他流之类的东西替换。
不利的一面?
您有这个DummyStream
,它只存在于您的代码中,并且在未定义NDEBUG
时使用LOG_STREAM
时会执行一些无操作。
相关文章:
- 正在查找文档以获得PS4平台的C++中的设备信息
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 将两个数组中的差异记录在第三个数组中
- 如何设置一个范围来提取我想要获得的信息
- 系统参数信息A 与 SPI_GETMOUSE 返回 0
- 为什么 gcovr 会生成空覆盖率统计信息?
- 如何实现具有多个平台__FILE__和__LINE__信息的 C/C++ 可变参数日志记录宏?
- Qt 错误:QSqlQuery::value:尝试从表中检索统计信息时未定位在有效记录上 (QComboBox)
- 使用流在C++中记录信息
- 我正在尝试用 c++ 制作一个日志记录框架,但信息没有传递给记录器的子组件,我做错了什么?
- 如何在文本文件中搜索员工记录(按名称)并仅显示其详细信息?
- QApplication::activeWindow()->windowTitle();保存此信息以每秒记录一次
- 捕获所有异常并记录信息
- Poco::Logger 不记录跟踪或调试级别日志,只记录信息级别及以上
- Windows Phone 8.1运行时-如何获取呼叫信息,如传入和传出呼叫的历史记录
- 创建一个二进制文件,向其中添加信息,并从中读取所有记录(电话簿)
- 如何检索或打印"Catch"信息记录缓冲区?
- 如何使信息记录更容易
- 记录器在崩溃后没有将记录的信息存储到文件中