5285|16

64

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

wince内存系统疑惑。 [复制链接]

在CE中运行我的程序,内部随着操作的不同会生成很多的非模对话框,操作完成后
回收内存销毁,肯定自己DELETE了所有的NEW出来的东东,打开系统属性查看内存使用情况,发现即使delete了内存依然是占用那么多!变化量很小,跟创建对话框之前的内存差量很大,100来K。
怀疑时另起一个对话框程序,内只有两个按钮,一个按钮new了一个10000个int类型的元素,另一个按钮delete这个数组。
当按了new出来的按钮看到系统内存增加了40K,很正确,但delete按钮按下去确发现
系统显示的内存依然没减少,这是为什么呀,,请指教。
void test::onbutton1()
{
   m_pIntArray = new int[10000];
   ASSERT(m_pIntArray);
}

void test::onbutton2()
{
   if(NULL != m_pIntArray)
   {
       delete []m_pIntArray;
   }
   m_pIntArray = NULL;
}
此帖出自WindowsCE论坛

最新回复

无论简单的代码还是复杂的代码,分配内存都在堆中,所以现象是一致的,你的代码比较复杂,又涉及到类问题,所以应该化简再做判断。  详情 回复 发表于 2007-5-22 20:19
点赞 关注
 

回复
举报

65

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
没人讲,在网上查到也有人出现类似问题,有高人给解释一下么。。
此帖出自WindowsCE论坛
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
WIN32程序?
此帖出自WindowsCE论坛
 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(初级)

4
 
如果是的话,可能是你的对话框处理函数中缺少DefWindowProc,这样的话,虽然窗口销毁了,但是窗口消息处理还在进行;或者是你拦截了WM_DESTRO消息,但是没有PostQuitMessage。
此帖出自WindowsCE论坛
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

5
 
win32的,可是很显然我用的两个按钮的测试程序不存在MESSAGE的,依然无法回收内存。
此帖出自WindowsCE论坛
 
 
 

回复

87

帖子

0

TA的资源

一粒金砂(初级)

6
 
只要你创建了对话框,就算你不作处理,消息还是存在的。
此帖出自WindowsCE论坛
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

7
 
这个是正确的结果,应该是WinCE内存管理机制造成的,你可以做个测试

1. click onbutton1 and then click onbutton2 检查一下内存状况

然后重复以上步骤,会发现内存只有第一次增加了 40k(==1000 * sizeof(int)),以后都不会再增加了,当进程销毁时,所有内存都释放了。不论你使用 new delete LocalAlloc or malloc等等,都无法改变这个事实。

以下是我的解释,当你的进程Process A 切换到 slot 0的时候,所分配的虚拟地址到物理地址的映射被系统保留了,这样当其他进程Process B切换到slot 0时,只要映射关系不冲突,就不会释放上次映射的那块内存(40k),所以当你查看时会发现少了,如果当前Process B需要占用那块地址,应该是会回收(40k)内存。这个机制的好处就是,可以做到进程间快速切换,因为上次的使用的内存块并没有马上清除,当Process A再次造访slot 0时,仍然有上次的数据,而不必重新从其他slot映射到slot 0。这个机制和调用DLL是类似的。

因为我没时间看源码,以上判断来自微软内存管理的资料,你可以想办法去微软求证^^。


此帖出自WindowsCE论坛
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

8
 
谢谢楼上的解答,我也知道可能是系统优化保留,这种简单的数据内存管理不再增加。但当是无模对话框的创建时,不停的创建不停的销毁,后期发现内存惊人,万不得已正在寻求内存池管理的横式,调试中。
此帖出自WindowsCE论坛
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

9
 
你用delete的时候内存确实是释放了,
但系统不会因为你释放了而马上收回, 它会不定时的自动收回,或者是当系统内存不够的时候,才去收回释放了的。呵呵
此帖出自WindowsCE论坛
 
 
 

回复

86

帖子

0

TA的资源

一粒金砂(初级)

10
 
我得看法,这是因为windows CE的进程堆只能增大不能减小的原因。系统属性里查看的内存是已被进程用VirtualAlloc分配的内存。new/delete操作的是进程堆,new操作在堆上分配内存,如果堆不够大系统会自动增大堆的占用内存空间,delete操作只是把内存释放回堆,堆却不会进一步把内存释放回系统。
你可以作个试验,用HeapCreate自己创建一个堆,用HeapAlloc/HeapFree在上面分配、释放内存,你应该会看到,随着HeapAlloc的使用系统可用内存会减少,HeapFree不会使系统可用内存增大,但是HeapDestroy应该会使系统可用内存增大。
此帖出自WindowsCE论坛
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

11
 
HeapDestroy效果是一样的,可用内存不会增大,我用VirtualAlloc 和VirtualFree测试过,一样不会增大,使用VirtualQuery 查询释放后的原分配地址空间会发现,内存页面仍然处于MEM_COMMIT状态,强行改变页面状态会造成系统崩溃,说明当前地址空间可能被其他进程使用。
此帖出自WindowsCE论坛
 
 
 

回复

55

帖子

0

TA的资源

一粒金砂(初级)

12
 
我的测试中VirtualFree以后内存确实增大了,而且分配页面都被释放了。HeapDestroy效果也是一样的。而且,如果你用HeapAlloc分配一个很大的内存快(比如说2MB),HeapFree也会立即把内存释放掉。如果VirtualFree都后内存都不能释放,那这个API肯定和他描述的不符。不知道你是怎么调用VirtualFree的?
此帖出自WindowsCE论坛
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

13
 
贴个自写的内存管理类。
#include
#include

struct MemInfo
{
        unsigned int iMemSize;
        bool bUse;
        void* pMem;//标识内存的起始地址,在m_pMem中
};

typedef CArray CMemArray;

//问题要不要考虑页面边界及字节对齐的问题???
class CMemoryManager  
{
public:
        bool HasInit();
        CMemoryManager();
        virtual ~CMemoryManager();
        void* MemNew(size_t size);
        void MemDelete(void* p);
        bool Init();//最开始来标识是否成功//整个实例只能运行一次
        CMemArray& GetArray();


private:
        void DoMemCombinate(int iIndex,MemInfo* pInfo);

private:
        void* m_pMem;
        CMemArray m_oMemArray;
        CCriticalSection m_cs;//对此对象的lock不关乎成员,等待此对象的信号
        HANDLE m_hHeap;

};

CPP:
CMemoryManager::CMemoryManager()
{
        m_pMem = NULL;
        m_hHeap = NULL;
        m_oMemArray.RemoveAll();
}

CMemoryManager::~CMemoryManager()
{
        for(int i = 0; i < m_oMemArray.GetSize(); i++)
        {
                MemInfo* pInfo = m_oMemArray.GetAt(i);
                delete pInfo;
                //dont delete pInfo->pMem;
        }
        m_oMemArray.RemoveAll();
        //256kb
        if(NULL != m_pMem)
        {
                HeapFree(m_hHeap,0x40000,m_pMem);
                HeapDestroy(m_hHeap);
        }
}

//分配堆,在堆中分出自己要用的内存
bool CMemoryManager::Init()
{
        m_hHeap = HeapCreate(HEAP_NO_SERIALIZE,0x40500,0x50000);
        if(NULL == m_hHeap)
        {
                return false;
        }
        m_cs.Lock();
        m_pMem = HeapAlloc(m_hHeap,HEAP_ZERO_MEMORY,0x40000);
        if(NULL == m_pMem)
        {
                m_cs.Unlock();
                return false;
        }
        //内存小,delete影响小
        MemInfo* pInfo = new MemInfo;
        if(NULL == pInfo)
        {
                m_cs.Unlock();
                return false;
        }
        pInfo->pMem = m_pMem;
        pInfo->iMemSize = 0x40000;
        pInfo->bUse = false;
        m_oMemArray.Add(pInfo);
        m_cs.Unlock();
        return true;
}

//new一块内存,实际分配要不要更大点?
//思想是找最小适合空闲块来分配
void* CMemoryManager::MemNew(size_t size)
{
        MemInfo* pTemp = NULL;//标识空闲块
        unsigned int uiSize = 0;
        for(int i = 0 ; i < m_oMemArray.GetSize(); i++)
        {
                MemInfo* pInfo = m_oMemArray.GetAt(i);
                if(NULL != pInfo)
                {
                        //找最小块
                        if(pInfo->iMemSize >= size && !pInfo->bUse)
                        {
                                if(uiSize <= 0)
                                {
                                        uiSize = pInfo->iMemSize;
                                        pTemp = pInfo;
                                }
                                else
                                {
                                        if(pInfo->iMemSize < uiSize)
                                        {
                                                uiSize = pInfo->iMemSize;
                                                pTemp = pInfo;
                                        }
                                }
                        }
                }
        }
        if(NULL == pTemp)
        {
                return NULL;
        }
        m_cs.Lock();
        if(pTemp->iMemSize == size)
        {
                pTemp->bUse = true;
                m_cs.Unlock();
                return pTemp->pMem;
        }
        else
        {
                MemInfo* pNewInfo = new MemInfo;
                pNewInfo->iMemSize = size;
                pNewInfo->bUse = true;
                pNewInfo->pMem = pTemp->pMem;
                pTemp->iMemSize -= size;
                pTemp->pMem = (void*)((DWORD)pTemp->pMem + size);
                m_oMemArray.Add(pNewInfo);
                m_cs.Unlock();
                return pNewInfo->pMem;
        }
        m_cs.Unlock();
        return NULL;
}

//回收空闲块,当空闲块的前一块或后一块也为空闲则合并
void CMemoryManager::MemDelete(void* p)
{
        if(NULL == p)
        {
                return;
        }
        for(int i = 0; i < m_oMemArray.GetSize(); i++)
        {
                MemInfo* pInfo = m_oMemArray.GetAt(i);
                if(NULL != pInfo)
                {
                        if(pInfo->pMem == p)
                        {
                                m_cs.Lock();
                                memset(pInfo->pMem,0,pInfo->iMemSize);
                                pInfo->bUse = false;
                                DoMemCombinate(i,pInfo);
                                m_cs.Unlock();
                                return;
                        }
                }
        }
}

void CMemoryManager::DoMemCombinate(int iIndex,MemInfo* pInfo)
{

        int iPre = -1,iNext = -1;
        if(iIndex > 0)
        {
                iPre = iIndex - 1;
        }
        if(iIndex < m_oMemArray.GetSize() - 1)
        {
                iNext = iIndex + 1;
        }
        bool bRemove = false;
        if( -1 != iPre)
        {
                MemInfo* pMemPre = NULL;
                pMemPre = m_oMemArray.GetAt(iPre);
                if(!pMemPre->bUse)
                {
                        pInfo->iMemSize += pMemPre->iMemSize;
                        pInfo->pMem = pMemPre->pMem;
                        bRemove = true;
                        //须最后移去
                        delete pInfo;
                }
        }
        if( -1 != iNext)
        {
                MemInfo* pMemNext = NULL;
                pMemNext = m_oMemArray.GetAt(iNext);
                if(!pMemNext->bUse)
                {
                        pInfo->iMemSize += pMemNext->iMemSize;
                        delete pInfo;
                        m_oMemArray.RemoveAt(iNext);
                }
        }
        if(bRemove)
        {
                m_oMemArray.RemoveAt(iPre);
        }
}

bool CMemoryManager::HasInit()
{
        return m_pMem?true:false;
}

CMemArray& CMemoryManager::GetArray()
{
        return m_oMemArray;
}
此帖出自WindowsCE论坛
 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

14
 
//测试程序,当不停的调用此函数会发现内存不增加,效果很好。
//但实际移植到有dialog的程序中并不理想,不知道是不是dialog的内存实际并不是
//sizeof(dialog类)那么大的。暂时没调了,那位老大给个解释谢谢,简单数据就很好。
void CMemoryManagerDlg::OnButton1()
{
        void *p = NULL;
        p = m_oMag.MemNew(sizeof(int)*10000);
        if(NULL == p)
        {
                return;
        }
        int *pm = new(p) int[10000];
        CMemArray& array = m_oMag.GetArray();
        MemInfo* p1 = array.GetAt(0);
        MemInfo* p2 = array.GetAt(1);
//        m_oMag.MemDelete(p);
//        MemInfo* p3 = array.GetAt(0);
}

void CMemoryManagerDlg::OnButton2()
{
        if(!m_oMag.HasInit())
        {
                if(!m_oMag.Init())
                {
                        MessageBox(_T("fail"));
                }
        }
}
此帖出自WindowsCE论坛
 
 
 

回复

81

帖子

0

TA的资源

一粒金砂(初级)

15
 
我前面说明了,只有第一次可用内存会出现不减少的情况,调用方法是很简单的,就是新建一个SDK工程,在一个菜单点击消息中,分配内存后马上释放,使用各种分配方式都一样。这个我用Heap Tracker也发现是同样现象。你用的6.0?
此帖出自WindowsCE论坛
 
 
 

回复

87

帖子

0

TA的资源

一粒金砂(初级)

16
 
简单的数据确实是只分配一次内存后期不再增加,如我上面的两个按钮例子,但是如动态的非模对话框却似乎不是这样的,可以试验的,我用evc4.0
此帖出自WindowsCE论坛
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

17
 
无论简单的代码还是复杂的代码,分配内存都在堆中,所以现象是一致的,你的代码比较复杂,又涉及到类问题,所以应该化简再做判断。
此帖出自WindowsCE论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表