我尝试通过使用#define
指令和宏在我们的代码中使用 log4cxx 进行封装。代码编译但运行时出现访问冲突,因为我认为流对象未正确初始化。
尝试使 log4cxx 可插入的头文件如下所示:
#ifdef USE_LOG4CXX
#include "log4cxx/logger.h"
#define LOG_DEBUG(msg) LOG4CXX_DEBUG(logger, msg)
#define LOG_INFO(msg) LOG4CXX_INFO(logger, msg)
#define LOG_WARN(msg) LOG4CXX_WARN(logger, msg)
#define LOG_ERROR(msg) LOG4CXX_ERROR(logger, msg)
#define LOGGER_DECL static const log4cxx::LoggerPtr logger
#define LOGGER_INIT(source,name) const log4cxx::LoggerPtr source::logger = log4cxx::Logger::getLogger(#name);
#else // use some other log method, e.g. stdout which worked fine
.cpp 文件的日志记录如下:
LOG_INFO("state(): " << old_state << " ==> " << new_state );
预处理器将 .cpp 文件扩展为:
{ if (logger->isInfoEnabled()) { ::log4cxx::helpers::MessageBuffer oss_; logger->forcedLog(::log4cxx::Level::getInfo(), oss_.str(oss_ << "state(): " << state_ << " ==> " << new_state), ::log4cxx::spi::LocationInfo("c:\\dev\\ezx-capi\\iserver-api\\iserver_client.cpp", __FUNCSIG__ , 190)); }};
old_state 和 new_state 的数据类型是int
.
运行时,应用程序失败:
std::basic_ostream<char>& operator<<(CharMessageBuffer& os, const V& val) {
return ((std::basic_ostream<char>&) os) << val;
}
在调试器中,问题看起来像CharMessageBuffer
对象有一个std::basic_streambuf
未初始化的成员,所以当它去追加值时,它就死了。(不过我不确定这个解释。)
一直钻下去,它死在std::basic_ostream
:
_Myt& __CLR_OR_THIS_CALL operator<<(int _Val)
{ // insert an int
ios_base::iostate _State = ios_base::goodbit;
const sentry _Ok(*this); // dies right here, in the constructor
无论如何,我意识到这与我如何使用宏调用 LOG4CXX 有关。(当我没有定义 USE_LOG4FXX 时,所有的日志语句都可以std::cout
正常工作。)
更新
另一条信息 - 似乎只有当我从静态库中调用日志记录时才会失败。如果我使用来自 EXE 项目的相同(或类似)宏,它根本不会失败。所以我似乎无法在某种单独的测试应用程序中复制这个问题。