• λ我爱Aspx >> Asp.Net >> 处理内存泄漏的一种MFC方法
  • 处理内存泄漏的一种MFC方法

  • :未知  Դ:internet  :2007-5-5 19:46:01  ؼ:
  • 信息产业部数据所

    廖 铮

    ---- Windows使用复杂的内存管理器控制和优化内存的使用(包括磁盘缓冲)。一旦内存管理出现纰漏就会导致内存泄漏。内存泄漏的实质一般是因为在堆上分配了某块内存但以后不再对其重新分配,使得该部分内存失去重用性。出现这一问题的多数应用程序一开始往往正常运行,所以要检测出该类问题是较为困难的。不过,要将其找出并得到正确的处理才更麻烦。大多数MFC应用程序允许Windows安全地管理分配给资源的内存,如果分配内存的组件不由系统所处理的话内存泄漏的危险就大大增加了。这里通过举例来讨论一些相关的问题。

    示例:多次重绘窗口导致内存泄漏

    ---- 我们简单建立一个STD的MFC工程MLeak,该程序首先创建逻辑字体,随后TextOut() 函数在窗口的客户区书写文本,如果程序类似图1(略)左那样持续再长时间你也看不到会出现什么奇怪的现象。但你用鼠标抓住窗口的边界改变窗口大小多次(多的时候要到数十次)就会看见窗口变成了图1右那样:字体出问题了。TextOut()函数仍然可以在窗口上书写文本,但是逻辑字体却没有得到正确的创建。一般会认为问题出在OnDraw()函数内的字体创建过程中。真是这样吗?

    查找和分析问题

    ---- 幸好有些MFC类和函数可以用于发现内存泄漏。添加相应代码就有助于检查CMLeakView类中存在的内存泄漏问题(关键的代码以粗体标识)。首先我们用ClassWizard为视图类加入 OnCreate() 函数,目的是为了在程序初始化时获得堆的有关统计数据。只要调用oldMemState.Checkpoint()函数即可做到这一点。接着OnDraw()函数内在完成与字体有关的全部工作后将执行以下附加的调试代码: #ifdef _DEBUG newMemState.Checkpoint(); if(diffMemState.Difference (oldMemState, newMemState)) { TRACE("Difference between first and now!\n\n"); diffMemState.DumpStatistics(); } #endif ---- 调用newMemState.Checkpoint() 将获得堆的最新情况,diffMemState.Difference()则在原始值和当前值出现差异时返回信息。统计结果通过调用diffMemState.DumpStatistics()被扔出。因为该信息包含在OnDraw()函数内,而OnDraw()函数响应WM_PAINT消息重绘屏幕窗口,则在每次改变窗口大小时将打印出统计结果,我们发现每次公布的统计数据的最后一行才有变化: Difference between first and now! (第一次统计信息的开始行) … … Total allocations: 87 bytes. (第一次统计信息的结束行) …… Total allocations: 132 bytes. (第二次统计信息的结束行) … … Total allocations: 14352 bytes. (最后一次统计信息的结束行) ---- 可以注意到每次重绘屏幕都导致整个分配区在增加,增加幅度为45字节,重绘一定次数后内存分配就到达了14,352字节。那么会不会是忘了为逻辑字体结构分配内存呢?我们再向OnDraw()函数中插入以下粗体代码: LOGFONT lf; … … memset(&lf,0,sizeof(LOGFONT)); … … ---- 结果如故,说明逻辑字体结构大小并没有与此发生必然联系。从OnDraw()函数中去掉字体创建过程并加入到OnCreate()中,使逻辑字体资源在创建窗口时得到创建,不过还是可以发现分配的整个内存仍然持续增加!于是修改OnDraw()如下: void CMLeakView::OnDraw(CDC* pDC) { CMLeakDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDC->TextOut(20, 200, "This program has memory problems"); #ifdef _DEBUG newMemState.Checkpoint(); if(diffMemState.Difference (oldMemState, newMemState)) { TRACE("Difference between first and now!\n\n"); diffMemState.DumpStatistics(); } #endif } ---- 问题仍然出现,而以下代码是OnDraw()中所增加的唯一代码: pDC- >TextOut (20, 200, "This program has memory problems"); ---- 将该行代码注释掉并重新编译、运行诊断程序。可以发现整个内存分配统计结果增幅为0。看来,分配给字符串的内存在屏幕每次重绘时被重新分配了。

    Ҷƪл˵?
  • һƪ使用ASP和Word进行服务器端拼写检查
    һƪJava会四分五裂吗?