我刚开始使用log4cxx做一个小应用程序来熟悉它。 我用Visual Studio 2005编译,没有警告或错误。 基本上看起来像:
#includes<...>
...
...
LoggerPtr logger(Logger::getLogger("MyApp"));
void main(...)
{
//some logs here
}
当我在尝试销毁全局 Logger 对象时遇到异常时关闭应用程序,它会按预期工作。 这是跟踪:
log4cxx.dll!apr_pool_cleanup_kill(apr_pool_t * p=0xdddddddd, const void * data=0x01cf6158, int (void *)* cleanup_fn=0x10174250) Line 1981 + 0x3 bytes
log4cxx.dll!apr_pool_cleanup_run(apr_pool_t * p=0xdddddddd, void * data=0x01cf6158, int (void *)* cleanup_fn=0x10174250) Line 2025
log4cxx.dll!apr_thread_mutex_destroy(apr_thread_mutex_t * mutex=0x01cf6158) Line 133
log4cxx.dll!log4cxx::helpers::Mutex::~Mutex() Line 57
log4cxx.dll!log4cxx::Logger::~Logger() Line 55 + 0xb bytes
log4cxx.dll!log4cxx::Logger::`vbase destructor'() + 0x19 bytes
log4cxx.dll!log4cxx::Logger::`vector deleting destructor'() + 0x5a bytes
log4cxx.dll!log4cxx::helpers::ObjectImpl::releaseRef() Line 46 + 0x39 bytes
log4cxx.dll!log4cxx::Logger::releaseRef() Line 63
log4cxx.dll!log4cxx::helpers::ObjectPtrT<log4cxx::Logger>::~ObjectPtrT<log4cxx::Logger>() Line 100 + 0x33 bytes
NodeBHeartBeat.exe!`dynamic atexit destructor for 'logger''() + 0x2b bytes
msvcr80d.dll!doexit(int code=0x00000000, int quick=0x00000000, int retcaller=0x00000001) Line 553
msvcr80d.dll!_cexit() Line 413 + 0xb bytes
msvcr80d.dll!__CRTDLL_INIT(void * hDllHandle=0x6c710000, unsigned long dwReason=0x00000000, void * lpreserved=0x00000001) Line 389
msvcr80d.dll!_CRTDLL_INIT(void * hDllHandle=0x6c710000, unsigned long dwReason=0x00000000, void * lpreserved=0x00000001) Line 214 + 0x11 bytes
ntdll.dll!774b9960()
任何人都知道为什么会这样? 感谢
答案 0 :(得分:3)
我设法通过简单地将“0”分配给记录器指针来解决问题。
魔术技巧位于文件src / main / include / log4cxx / helpers / objectptr.h中的log4cxx源代码内
也就是说,releaseRef()可以间接控制对象销毁顺序。
...
...
ObjectPtrT& operator=(const int& null) //throw(IllegalArgumentException)
{
//
// throws IllegalArgumentException if null != 0
//
ObjectPtrBase::checkNull(null);
T* oldPtr = exchange(0);
if (oldPtr != 0) {
oldPtr->releaseRef();
}
return *this;
}
...
...
因此,对于您的代码,只需在末尾添加一行:
#includes<...>
...
...
LoggerPtr logger(Logger::getLogger("MyApp"));
void main(...)
{
//some logs here
logger = 0; // RELEASE REFERENCE TO POINTER
// Make sure no other reference to logger exist
// ie: a thread that used a copy constructor on the logger object.
}
答案 1 :(得分:1)
将LoggerPtr放在类中可以解决此问题,例如:
class A
{
public:
A()
{
string appPath = getenv("APPDIR");
appPath = appPath + "/" + LOG4CXX_CONFIG_FILE_NAME;
// Load configuration file
DOMConfigurator::configure(appPath.c_str());
m_serviceLogger = Logger::getLogger("tuxedoService");
}
void log()
{
LOG4CXX_ERROR(m_serviceLogger, "This is a Test log");
}
private:
LoggerPtr m_serviceLogger;
};
A a;
int main()
{
a.log();
return 0;
}
请注意,如果使用成员函数(如init()
)替换构造函数,并在日志函数之前调用main中的init()
,则会导致段故障,如您所述。
这是一个取消初始化序列问题。
答案 2 :(得分:0)
我会在这里与我们遇到的类似情况发生声响。我们引用了一个未在我们的log4cxx配置文件中定义的记录器。在某些版本的库中,这很好,但在其他版本中它导致堆栈跟踪如下:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x00007ffff72b3892 in std::_Rb_tree<std::string, std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> >, std::_Select1st<std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> > >, std::less<std::string>, std::allocator<std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> > >*) ()
from /usr/lib/liblog4cxx.so.10
#2 0x00007ffff72b387b in std::_Rb_tree<std::string, std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> >, std::_Select1st<std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> > >, std::less<std::string>, std::allocator<std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> > >*) ()
from /usr/lib/liblog4cxx.so.10
#3 0x00007ffff72b387b in std::_Rb_tree<std::string, std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> >, std::_Select1st<std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> > >, std::less<std::string>, std::allocator<std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> > > >::_M_erase(std::_Rb_tree_node<std::pair<std::string const, log4cxx::helpers::ObjectPtrT<log4cxx::Logger> > >*) ()
from /usr/lib/liblog4cxx.so.10
#4 0x00007ffff72b1a2a in log4cxx::Hierarchy::~Hierarchy() () from /usr/lib/liblog4cxx.so.10
#5 0x00007ffff72b1c49 in log4cxx::Hierarchy::~Hierarchy() () from /usr/lib/liblog4cxx.so.10
#6 0x00007ffff72c982a in log4cxx::spi::DefaultRepositorySelector::~DefaultRepositorySelector() ()
from /usr/lib/liblog4cxx.so.10
#7 0x00007ffff72c95bc in log4cxx::helpers::ObjectPtrT<log4cxx::spi::RepositorySelector>::~ObjectPtrT() ()
from /usr/lib/liblog4cxx.so.10
#8 0x00007ffff52e8e25 in __cxa_finalize () from /lib/x86_64-linux-gnu/libc.so.6
#9 0x00007ffff727c2b6 in ?? () from /usr/lib/liblog4cxx.so.10
#10 0x000000000000005b in ?? ()
所以我们只需删除引用,一切都很好。这是一个非常无害的陈述:
LoggerPtr logger(Logger::getLogger("someloggerthatdoesnotexist"));