//=====================================================================
//TITLE:
// WinCE的内存泄露
//AUTHOR:
// norains
//DATE:
// Thursday 28- January-2010
//Environment:
// WINDOWS XP
// WINDOWS CE 5.0
//=====================================================================
在WinCE的环境下大家都使用过STL,单不知道大家有没有发现,这里有个致命的问题。如果容器的数据量比较大,会导致无法释放内存资源。不信?我们来看一下下面这个测试代码:
这个代码简单到只要学过STL的都知道是咋回事。意思无外乎是不停地往map容器插入数值,完成之后通过clear删掉。外面的{}是定死了mpTmp的作用域,让mpTmp执行到{}之外后会自动调用析构函数。
代码没什么,我们来看看实际的运行情况。
首先是在WinXP环境,内存监控我们直接采用任务管理器就好了。
1).程序执行到代码(1)
这时候的内存占用量截图如下:
2).程序执行到代码(2)
此时.clear()函数尚未执行,只是刚刚完成数值的插入。内存的耗用如下:
很明显,内存有显著的上涨。
3).程序执行到代码(3)
此时已经调用了clear函数,内存占用量如下:
由此可见,内存已经释放,基本上回到了分配前的大小。
那么接下来我们看看在WinCE下的情况。代码执行的步骤和在WinXP相同,但监视内存的工具采用Windows CE Remote Performance Monitor。
因为该工具是使用曲线图来表示,为了更方便观看,所以我们直接在曲线图中表示代码执行的步骤:
是不是很诡异?没错,你没有看错!在调用了clear之后,内存占用根本就没有降低,还是保持之前的水准。即使mpTmp生存期已过,调用了析构函数,所分配的内存依然没有释放!
也许你还想进一步查看程序究竟是哪块内存没有释放完毕,打算祭出Remote Heap Walker来定位查看,但诡异的事情发生了:你在列表中根本就找不到你正在调试的这个测试程序!
为什么我说是数据量大的时候,资源是无法释放呢?你可以尝试一下,将示例中的循环次数改为1024。你会发现,一切都正常了,资源能释放了。
相同的问题,不仅在map存在,其实在string也会有。即使你采用的是推荐的swap方式,在数据量暴多的时候,依然无法正确释放。
实验和推测进行到这里,可能大家会有这么一种直觉:微软的STL库有问题!一开始,我也是这么想的。因为我用的是VS2005,所以又拿了VS2008的STL试着来尝试一下,发现结果依然如此。
也许到了这里,矛头大家可能还是指向STL。但实际上,即使你不是使用STL,只要你使用了堆,并且数据量够大,那么问题同样会出现。
我们可以试试这个代码:
这段只是采用new进行分配的代码,问题依然如前所示。
截止到本文完稿为止,我还是没有找到解决的方法,唯有看着那白白耗费的资源束手无措。根据经验推测,产生这问题很可能是因为WinCE 5.0的内存管理机制,但我目前没有WinCE 6.0的平台可供测试,所以也无法确定。
最后,列出我的测试平台,在以下平台的测试都会出现如文中所提到的现象:
1. TCC7901, WINCE 5.0
2. AU1200, WINCE 6.0