避免內存泄露

問題闡述

      一個大型的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;
}
程序輸出結果以下:
相關文章
相關標籤/搜索