=====================================摘抄帖子====================================
http://topic.csdn.net/t/20031212/08/2555151.html#
-----------------------------------------------------------------------------------------------------------------------------
我用EVC写了一个在WINCE(4.0)下运行MFC程序,里面我用NEW为字符
串分配了一个10K的空间,然后用DELETE释放,可是内存并没有被收
回,怎么回事呢?
谢谢
-------------------------------------------------------
如果楼主只是看DELETE释放后,指针的值的话,那么我告诉您:指针的值不会是空的。
--------------------------------------------------------
我是用的循环分配,然后加入一个数组里,然后在循环释放。总共要分配20M左右,所以通过系统属性也能看出来
循环里的每次分配大约10K,循环次数很多
-------------------------------------------------------
你查的是dwAvailVirtual 还是dwAvailPhys ?
我觉得这种方法并不可靠,因为你分配的是虚拟内存空间,至于OS何时去申请实际的物理空间那就是OS的事了。
------------------------------------------------------
我查的是dwAvailPhys,
我做过一次这样的实验,当启动程序后,通过看控制面板里的系统属性,总共内存数和使用内存数(可用内存30多M),然后我点击程序一个按钮,开始循环分配和释放,当释放完后弹出了一对话框,我再通过系统属性看到以使用内存增加了20多M,还有10M左右可用,当我点击对话框的OK按钮后,程序会接着再一次分配20M,可是这时失败了,可以得到这时可用内存以不足20M,开始循环分配后释放的并没有释放。
在实验中发现,如果每次分配的空间大些,就可以正常收回,小了就不行,而且我点击按钮分配释放后,再点这个按钮,内存基本就不会变化了,是不是CE系统做了些什么处理?
--------------------------------------------------------
你最好把代码贴出来,这应该是个很简单的问题,new和delete 创建的只是seperate heap
--------------------------------------------------------
一点陋见供参考:
用NEW分配内存时,是在进程的本地堆中分配,本地堆是动态增长的,进程的本地堆初试化是1M的空间。当你NEW时它只在虚存中保留空间,而不提交物理存储,当你访问这段空间时,会产生一个异常,操作系统就在这个异常中提交物理存储,实现堆大小的动态增长。所以,你分配内存和释放内存是是否影响物理内存的可用数是由操作系统的内存管理机制来决定的。一般说来,分配时它不会立即提交物理存储,释放时也不一定立即释放物理存储(如果已提交的话),具体的实现取决于操作系统的设计。
---------------------------------------------------------
一个系统可分配的空间是限的,记得在C语言下,连续分配65504字节的内存空间时,只会成功一两次(具体记不清楚了)。但我没有试,分配后delete,然后再分配是否能成功。
楼主可以在C语言下做做试验,看看结果如何?
----------------------------------------------------------
我在WINDOWS CE.NET 4.20 下也测试过在堆中分配内存,我是开了3个线程,同时在堆中分配内存,每次5M,在对这5M的数据操作,然后释放在分配。大概运行了4个小时,没有发现不能回收的问题。在CE下用动态内存分配要注意一下几点:
1.每个进程只有32M的虚地址空间,你的物理内存是被对象存储空间和所有的进程共享。
2.在堆中长时间分配释放内存时间,会产生碎片,CE好像不支持内存碎片整理。
我觉得你好好检查一下程序代码,我记得在CE下一次分配很大的内存好像是不一定成功,有一个策略在里面。具体细节我记不清了。你可以分配小一些的内存试试。
还有:因为CE是一个多任务操作系统,在你分配的同时你能否确定其它进程没有占用内存。
--------------------------------------------------------------
堆内存的提交和回收我觉得有点向C++中向量中的内存分配管理办法。它有一个最小的管理粒度,满足这个条件时才真正的提交和回收物理内存。物理内存可能被提交了,但并没有使用,操作系统不会再分配给别的进程用,除非他被回收。操作系统为了提高效率应该会允许少量的物理内存不被回收,待积累到一定的程度再回收。
-------------------------------------------------------------
在CE下的虚地址空间是以64K为边界管理的,物理内存是分页管理,页面的大小与CPU有关。可以肯定的是在释放内存时,只有整个页面的内存都被释放了这个物理页面才会被释放,才能再被利用。但是什么时候释放好像在各个操作系统上都不一样,也没有任何资料可以查。有兴趣的化你可以去看看CE下有没有公开内存管理的代码。
我建议你如果频繁的在堆中分配内存的话,你要自己创建个堆,在这个堆中分配。可能需要重载NEW和DELETE。这样会提高很多系统的性能。
-------------------------------------------------------------
我至今没时间尝试你说的情况,但我已经看过了Douglas Boling 最新的《PROGRAMMING MICROSOFT WINDOWS CE.NET》第三版英文原著,在第七章内存管理中没有直接回答过你提到的问题,但从侧面可能解答了这个问题,建议你去看看。有几点要注意:
1.在WinCE中,微软推荐的是使用VirtualAlloc,LocalAlloc,HeapAlloc 进行内存分配操作,即直接操作虚拟内存页,本地堆和分离堆,来进行分配,比如malloc new 这类的操作是会导致内存泄漏或异常的,因为这是C or C++ run time的函数而不是WinCE的API。
(本地堆默认的大小是 188kb 但是会自动扩大)
2.虚拟内存分配是以64k 为边界的,这决定了一个最大值, 32mb/64k= 511 次 但是除去堆栈和代码,只能分配475次,如果你超过了,我觉得你在分配时可能出错了。你最好在分配时要加上判断,每次分配返回的指针是否为NULL或失败,如果有失败,那么后面的所有结论都是错的。注意,物理内存剩余,并不表示你虚拟内存有剩余。
3.WinCE操作系统有对内存临界的程度的判断,并作出相应处理,当你分配内存到最后几次的时候,内存可能很少了,系统会进入临界状态,首先传递WM_HIBERNATE消息给最下面的应用程序,如果应用程序接到处理后开始释放栈,如果仍然没有足够的空间,就开始限制内存分配操作,再不行就由下自上开始关闭应用程序,直到最后,系统再通过一些秘密(^O^)的操作就完成了整个内存回收。
你如果对我的回答不满意,再推荐你去www.smartphonedn.com 里的程序设计论坛去问,那里有微软的MVP ,有很多问题我都从他那里得到了解答。
补充一点,如果是分配虚拟内存,你即使只分配10k,系统也会为你保留64k,这是最小的分配值。
----------------------------------------------------------------
建议用VirtualAlloc一次性分配一个大块的内存空间
当用VirtualAlloc分配一个>=2MBytes的内存时,系统并不是从每个进程32MBytes 的Slot里分配,而是从系统的Large Memory Area里分配.也就是说可以不受每个进程32MBytes 的制约.
你只要自己管理这块内存空间,可以节省多次NEW /DELETE带来的麻烦.
----------------------------------------------------------------