2

log4cxx に慣れるために小さなアプリを作成して、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()

なぜこれが起こっているのか誰にも分かりますか?ありがとう

4

3 に答える 3

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.
}
于 2015-03-18T13:55:31.360 に答える
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;
}

コンストラクターを のようなメンバー関数に置き換え、ログ関数の前に maininit()を呼び出すと、再度説明したようにセグメント違反が発生することに注意してください。init()

これは、初期化シーケンスの問題です。

于 2012-04-09T08:03:16.503 に答える