一直用log4cpp的library方式(非DLL)连接到自己的程序中(可从我的资源中下载)
最近发现一个内存泄漏的问题,感觉很奇怪:
从主程序中传入一个Category对象的指针pLog到类实例Ca中,Ca对象存在于独立的DLL中并且用 LoadLibrary(..)的方式装载到主程序。
当DLL被装载后,Ca开启一个线程Ta并把pLog传入到此线程Ta中。
主程序与Ca对象全部以static library的方式引用了 log4cpp。
OK,出现内存泄漏的情况是:只要线程Ta中调用了日志的任何函数(debug,info...),就会出现'泄漏'(当然这个不一定称为泄漏,请看我以前的文章)。
查了这个问题的原因,也大概看了一下代码。终于找到了问题的所在:
当log4cpp以 static library 的形式被调用时,任何调用的对象都会 'Copy'一份到自己的‘空间’里。所以,Ca所在的DLL会拥有一份,主程序也会有一份,而每一份log4cpp的COPY都会生成一个
namespace {
threading::ThreadLocalDataHolder<NDC> _nDC;
}
实例。(请参看:NDC.CPP 27行)
_nDC对象的用处看其定义就应该明白大概的了! ---- 与线程有关!(具体请大家自己看代码吧 :( )
当在 Ta 中调用时,使用的_nDC 是主线程是实例!
在线程 Ta 的最后调用 log4cpp::NDC::clearCurrentThreadNDC() 时,使用的_nDC则是当前Dll内的一个实例(请看我的另一文章http://blog.csdn.net/ani/article/details/6372025),根据不同的实例对查找资源,当然就找不到要删除的内存了!
你会发现:那此时不是有两个一模一样的全局对象了! 名字也相同?!
是的,这是允许的!大家可以去查询一下相关的资料!(http://stackoverflow.com/questions/2928957/is-it-possible-to-declare-multiple-static-variable-with-same-name-in-a-single-c-f)
所以,解决的方案是:把 log4cpp 的 static library 的使用方式换成 DLL 的方式!保证在一个 process 中,只有一个 _nDC 实例存在!
(我已经编译好了一份,大家可以在这里下载:http://download.csdn.net/detail/Ani/3648356)
有问题请指正!
欢迎转载!