避免内存泄露

问题阐述

      一个大型的C++程序中最容易出现,也是最头疼的一个问题就是内存泄露,即忘记释放已经申请的内存,形成程序占用的内存不断上升,系统性能不断降低,甚至形成内存耗尽而致使程序崩溃。在Java中提供自动垃圾回收机制,程序在什么时候的时机将回收内存,C++语言一直没有将这种机制做为语言的内部机制,可是它也提供了足够的灵活机制,使开发人员有效地避免内存泄露。html

二、 内部封装ios

      能够将分配和释放的过程封装到一个类中,即在构造的时候申请内存,析构的时候释放内存,从而保证没有内存泄露。下面是一个简单的封装类。 数组

#include < iostream >
   #include < cstring >
using namespace std;
class AutoNewDel
{ private
    char* m_szBuf; 
    unsigned int m_nSize;
public
    AutoNewDel(unsigned int n=1)
    {         m_szBuf=newchar[n];         m_nSize=n;     }
    ~AutoNewDel()     {         if(m_szBuf!=NULL)    //提供安全机制
        {             delete[] m_szBuf;    //删除字符数组 
            m_szBuf=NULL;    //防止出现野指针         }    
}
    char* GetBuf()    
        return m_szBuf;     };
} ;
void fun()
    AutoNewDel tmpObj(100); 
    char* p= tmpObj.GetBuf(); 
    strcpy(p,"one world, one dream"); 
    cout<<p<<endl;
}
int main()
{     fun(); 
    cout<<"exit main"<<endl; 
    return0;
}
      在这个例子中,封装了char类型的内存分配和删除,当声明对象tmpObj时,便可得到相应的内存,并且这个内存再tmpObj对象的做用域推出时自动释放,不须要开发人员显示的调用delete来释放了,避免了因为忘记释放内存而引发的内存泄露错误。       本例给出了一个最基本的思路,可是仍是存在不少问题的,好比复制构造函数和复制的问题。下面将演示这个例子的不足,修改函数fun(),增长一个赋值语句,以下:
void fun() {   
AutoNewDel tmpObj(100);    
AutoNewDel tmpObj2=t mpObj;//这里是增长的语句
char* p= tmpObj.GetBuf ();   
strcpy(p,"one world, one dream");
cout<<p<<endl; }
      在这个类中并无实现复制构造函数,所以编译器自动构造一个默认的复制构造函数,执行位复制操做,即将对象tmpObj的内容逐字地复制到对象tmpObj2中,两个对象中的m_szBuf指向同一块内存,当对象销毁时, m_szBuf会被销毁两次,从而形成程序错误(本博客还有一篇随笔说明相关的内容,随笔地址为:C++ primer plus第十一章 使用类的程序。简单的解决办法就是禁止复制构造函数,在类中声明复制构造函数为私有。可是这样治标不治本,它限制类的功能实现。能够经过一个引用一个计数的方法,即避免了对同一块内存的屡次删除,也容许复制构造函数。             引用的计数的原理是这样的,就是对要使用的内存维护一个计数器,记录当前有多少指针指向这块内存。当有指针指向这块内存时,计数器加1;反之,当指向这块内存指针销毁时,计数器减1。当这块内存的计数器为0时,才容许删除这块内存。能够在类的构造函数和析构函数中分别完成加1和减1的操做。代码以下:
#include < iostream >
#include < cstring >
using namespace std;
class AutoNewDel
{ // Attribute
private
    char* m_szBuf; 
    unsigned int m_nSize; 
    int* m_count;    //新增长的语句
public
    AutoNewDel(unsigned int n=1)//在构造函数中申请内存
   
        m_szBuf=newchar[n]; 
        m_nSize=n; 
        //新增长的语句 
        m_count=newint
        *m_count=1
        cout<<"count is : "<<*m_count<<endl; 
    }
    //新增长的复制构造函数 
    AutoNewDel(const AutoNewDel & s)
    {         m_nSize=s.m_nSize; 
        m_szBuf=s.m_szBuf; 
        m_count=s.m_count; 
        (*m_count)++
        cout<<"count is : "<<*m_count<<endl; 
    } 
    ~AutoNewDel()
    {    
     (*m_count)--
        cout<<"count is : "<<*m_count<<endl;//新增长的两条语句         
        if(*m_count==0)
       
            cout<<"buf is deleted"<<endl; 
            if(m_szBuf!=NULL)    //提供安全机制
            {                 delete[] m_szBuf;    //删除字符数组 
                m_szBuf=NULL;    //防止出现野指针 
                if(m_count!=NULL)
               
                    delete m_count; 
                    m_count=NULL; 
                } 
            } 
        } 
    }
    char* GetBuf()    
        return m_szBuf;     };
} ;
void fun()
    AutoNewDel tmpObj(100); 
    char* p= tmpObj.GetBuf(); 
    strcpy(p,"one world, one dream"); 
    cout<<p<<endl;  
    AutoNewDel tmpObj2=tmpObj; 
    cout<<"tmpObj2.m_szBuf = "<<tmpObj2.GetBuf()<<endl;
}
int main()
    fun(); 
    cout<<"exit main"<<endl; 
    return0;
}
程序输出结果以下:
相关文章
相关标签/搜索