c++內存泄漏方面的知識

內存泄漏和內存溢出

內存溢出 out of memory:是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。
內存泄露 memory leak:是指程序在申請內存後,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積後果很嚴重,無論多少內存,遲早會被佔光。
memory leak會最終會導致out of memory!

常見的內存錯誤

  1. 內存申請未成功但是使用了它,產生原因:
    這是編程新手常犯這種錯誤,因爲他們沒有意識到內存分配會不成功。
    解決方法

    在使用內存時候記得進行null判斷
    如果指針 p 是函數的參數,那麼在函數的入口 處用 assert(p!=NULL)進行檢查。
    如果是malloc和new申請的內存記得進行(p!=null)或者(p==null)判斷

  2. 內存分配雖然成功,但是尚未初始化就引用它,犯這種錯誤主要有兩個起因:
    一是沒有初始化的觀念。
    二是誤以爲內存的缺省初值 全爲零,導致引用初值錯誤(例如數組)。
    解決方法

    內存的缺省初值究竟是什麼並沒有統一的標準,儘管有些時候爲零值,我們寧可信其無不可信其有。如果定義的是數組的話,可以這樣初始化: int a[10] = {0}; 或者用memset 函數來初始化 memset(a,0,sizeof(a))

  3. 內存分配成功並且已經初始化,但操作越過了內存的邊界,產生原因:
    使用數組時經常發生下標“多 1”或者“少 1”的操作
    解決方法

    在使用for循環,或者有邊界的操作的時候一定要注意邊界處理

  4. 忘記了釋放內存,造成內存泄露,產生原因:
    含有這種錯誤的函數每被調用一次就丟失一塊內存。
    剛開始時系統的內存充足,你 看不到錯誤。
    終有一次程序突然死掉,系統出現提示:內存耗盡。
    這種情況在一個函數裏面中間進行了return操作,然後在return之前申請了內存,但是沒有釋放發生的情況很多比如這樣:

      void Func(void)
    {
       char *p = new char[10];  
       ......  
       if(某個條件)
       {
       		return; //在此處直接return 並沒有調用delete p 造成內存泄漏
       }
       ......
    

解決方法
> 動態內存的申請與釋放必須配對,程序中 malloc 與 free 的使用次數一定要相同,否 則肯定有錯誤(new/delete 同理)。

  1. 釋放了內存卻繼續使用它,產生原因:
    一是程序中的對象調用關係過於複雜,實在難以搞清楚某個對象究竟是否已經釋放了內 存,此時應該重新設計數據結構,從根本上解決對象管理的混亂局面。
    二是return 返回了指向棧空間的指針或者引用舉個例子(下面是返回的指針,引用類似):

    此處返回了棧空間的指針,如果對外調用者使用了,會造成不可預估的情況
    char *Func(void)
    {
       char str[]="hello world"; //str數組創建在函數堆棧上,並用字符串常量來初始化
       ......
       return str; //該句存在隱患,str指向的內存單元將被釋放
    
    這種雖然使用時候沒有什麼問題是在程序的靜態數據區但是這種東西一直存在,設計上感覺還是有問題
    const char *Func(void)
    {
       (const)char *pStr="hello world";  //字符串常量存放在程序的靜態數據區,
        //pStr指針雖然是在棧上定義的,但當函數返回時,它指向的那個內存地址,也就是字符串"hello world"還是存在的,並沒有被釋放
        return pStr;  //返回字符串常量的地址,沒有問題
    }
    

    三是使用 free 或 delete 釋放了內存後,沒有將指針設置爲 NULL。導致產生“野指針”。

自己寫代碼檢測泄漏方法

重載new/delete操作符
重載new/delete操作符,用list或者map記錄對內存的使用情況。new一次,保存一個節點,delete一次,就刪除節點。
最後檢測容器裏是否還有節點,如果有節點就是有泄漏。也可以記錄下哪一行代碼分配的內存被泄漏。
類似的方法:在每次調用new時加個打印,每次調用delete時也加個打印。

檢查內存泄漏工具

valgrind工具
工具檢測原理
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章