控件讲了这么久,其实我的程序有两个Bug不知道大家有没有发现,这两个Bug都不会报错,对程序运行来说都没有阻碍,但是这种Bug对整个代码来说是一个很大的安全隐患。
什么是内存泄漏
内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
简单的说就是new完之后没有delete。当然,内存泄漏还不止这一点点。但是对于新手来说,大部分的内存泄漏都是因为new的原因 照成的。
内存泄漏对程序的影响?
内存泄漏是造成应用程序OOM的主要原因之一。我们知道Android系统为每个应用程序分配的内存是有限的,而当一个应用中产生的内存泄漏比较多时,这就难免会导致应用所需要的内存超过系统分配的内存限额,这就造成了内存溢出从而导致应用Crash。
首先来看看消息溢出的报错,分为两种,先来
首先来看看前六个内存泄露,其实他们就是属于最常见的内存泄漏,我在new完窗口后没有将窗口释放掉
那么这类问题很好解决,首先三个是成员函数,所以我们只要在析构中delete这三个对象就可以了。
CtabView::~CtabView() { if(m_dlg1) { delete m_dlg1; m_dlg1 = NULL; } if(m_dlg2) { delete m_dlg2; m_dlg2 = NULL; } if(m_dlg3) { delete m_dlg3; m_dlg3 = NULL; } }
下面这个内存泄漏比较麻烦,没法一眼看出来原因,所以我们一点一点来分析
检查定位泄漏的内存块
首先教大家如何定位泄漏的内存块。在我们觉得有内存泄露的地方添加函数,参数是内存块,根据上面的图显示内存块为373;
_CrtSetBreakAlloc(373)
如果_CrtSetBreakAlloc函数检测到内存泄露,例如我放在创建选项卡上方。他会中断报错,并跳进这里,这就说明程序在这里还是有问题的,咱们得继续往下找
如果说,我把函数放在OnCreat下面,那么这个程序调试就没有问题
通过这样检测内存块,我们可以判断出是OnCreat这里发生了内存泄露,但是OnCreat是微软的API函数,我也没有动态调用,为何会出现内存溢出呢?
再仔细看一下报错信息
Detected memory leaks! Dumping objects -> {373} client block at 0x05903290, subtype c0, 212 bytes long. a CMFCVisualManager object at $05903290, 212 bytes long Object dump complete.
他提到了CMFCVisualManager 这个类,那么有可能这个泄露是跟这个类有关,上网上搜了一下,原理是原因在于VS2008中MFC程序中的应用程序类都派生自CWinAppEx,VS 2008的程序里有一个CMFCVisualManager类的全局对象,负责管理可视化界面,具体来说就是一个单件(设计模式中的单件模式),CWinAppEx类的ExitInstance函数可以析构这个对象。但是以往的MFC程序的应用程序类都派生自CWinApp,因为需要在ExitInstance函数手动这个类对象,具体就是在应用程序类的ExitInstance函数添加代码。
简单的来说CWinAppEx::ExitInstance()函数自动对工程中所采用的CMFCVisualManager对象(如CMFCPropertyGridCtrl、CVCVSListBox等控件)释放资源,而CWinApp::ExitInstance()没有这个能力,因此需要重写。所以这个泄露大致有两种解决方案。
1.CWinApp::ExitInstance()没有释放能力,所以所以我们需要手动释放
在ExitInstance()添加代码
CMFCVisualManager::DestroyInstance( TRUE );
2.ExitInstance()的自动释放能力是基于CWinAppEx类的,所以我们只需要将CxxxApp的父类改为CWinAppEx就可以,同时CWinAppEx是自动实现ExitInstance()方法的,所以将代码自动生成的ExitInstance()方法注释掉就好。
退出后没有任何一处
另外我还发现项目本身还带一些小Bug,比如点到第三页直接跳出来关闭菜单,第二页和第三页颜色不知道为什么会变得一样,这个需要慢慢解决