2011-07-15 53 views
2

我剛開始用log4cxx做一個小應用來熟悉它。我用Visual Studio 2005編譯,沒有警告或錯誤。 基本上看起來像:log4cxx在〜Logger上拋出異常

#includes<...> 
... 
... 
LoggerPtr logger(Logger::getLogger("MyApp")); 

void main(...) 
{ 
    //some logs here 
} 

它按預期工作,直到我關閉應用程序時,我得到一個異常,而試圖破壞全球記錄儀對象。 這裏是跟蹤:

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() 

任何人有任何想法,爲什麼會出現這種情況? 感謝

回答

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()和日誌之前調用主init()功能,它會導致段錯誤,因爲你再次描述。

這是一個去初始化序列問題。

2

我設法通過簡單地將「0」分配給記錄器指針來解決問題。

的魔術位於log4cxx源代碼內在文件src /主/包含/ log4cxx /助手/ objectptr.h

即,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. 
} 
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"));