C/C++ 記憶體管理問題

來源:互聯網
上載者:User

標籤:

記憶體配置方式有三種:
(1) 從靜態儲存地區分配。記憶體在程式編譯的時候就已經分配好,這塊記憶體在程式的整個運行期間都存在。例如全域變數,static 變數。

(2) 在棧上建立。在執行函數時,函數內局部變數的儲存單元都可以在棧上建立,函數執行結束時這些儲存單元自動被釋放。棧記憶體分

   配運算內建於處理器的指令集中,效率很高,但是分配的記憶體容量有限。

(3) 從堆上分配,亦稱動態記憶體分配。程式在啟動並執行時候用 malloc 或 new 申請任意多少的記憶體,程式員自己負責在何時用 free 或

   delete 釋放記憶體。動態記憶體的生存期由我們決定,使用非常靈活,但問題也最多。動態記憶體的申請與釋放必須配對,防止記憶體流失。

 

在使用記憶體之前檢查指標是否為 NULL。如果指標 p 是函數的參數,那麼在函數的入口處用 assert(p!=NULL)進行檢查。

如果是用 malloc 或 new 來申請記憶體,應該用 if(p==NULL) 或 if(p!=NULL)進行防錯處理。

 

記憶體的預設初值究竟是什麼並沒有統一的標準,儘管有些時候為零值,我們寧可信其無不可信其有。所以無論用何種方式建立數組,

都別忘了賦初值,即便是賦零值也不可省略。

 

注意不要返回指向“棧記憶體”的“指標”或者“引用”,因為該記憶體在函數體結束自時被動銷毀。

使用 free 或 delete 釋放了記憶體後,將指標設定為 NULL。以防產生“野指標”。

 

數組名對應著(而不是指向)一塊記憶體,數組名相當於一個常量指標,其地址與容量在生命期內保持不變,只有數組的內容可以改變。

指標可以隨時指向任意類型的記憶體塊,它的特徵是“可變”,所以我們常用指標來操作動態記憶體。指標遠比數組靈活,但也更危險。

 

對於同一個char型字串char str[] = "Hellow":

strlen(str)的值為6  ,求的是這個字串有效字元的個數,不包含用於結束字串的   0  

sizeof(str)的值為7 , 求的是這個變數一共佔用記憶體的位元組數,當然包含最後一個用於結束字串的  0 。

 

對於char  *p = str  ;   sizeof(p)的值為int型變數在記憶體中佔用的容量。C++/C 語言沒有辦法知道指標所指的記憶體容量。

注意當數組作為函數的參數進行傳遞時,該數組自動退化為同類型的指標。

void Func(char a[100])
{
  cout<< sizeof(a) << endl;     // 4 位元組而不是 100 位元組

 

如果函數的參數是一個指標,不要指望用該指標去申請動態記憶體。 

GetMemory(str, 200)並沒有使 str 獲得期望的記憶體,str 依舊是 NULL。(pass by value)

void GetMemory(char *p, int num)
{
  p = (char *)malloc(sizeof(char) * num); //系統會開闢一個臨時儲存區儲存p 的值,這裡的p不是原來那個p     pass by value
}

如果非得要用指標參數去申請記憶體,那麼應該改用“指向指標的指標”。

void GetMemory2(char **p, int num)
{
  *p = (char *)malloc(sizeof(char) * num);
}

 

char * Test1(void)
{
  char str[] = "Hellow!";   //這裡強調不要用 return 語句返回指向“棧記憶體”的指標。因為str是字串,故str會在棧中建立。
  return str;
}

char *Test2(void)
{
  char *pStr = "Hellow!";//因為 "Hellow!" 是字串,故其會儲存在靜態儲存區,而pStr只是一個指標,根據pass by value , 即使棧中pStr被消除,“Hellow”依舊存在
  return pStr;
}

 

free和delete只是把指標所指的記憶體給釋放掉,但並沒有把指標本身幹掉。如果此時不把 指標 設定為 NULL,會讓人誤以為 p 是個合法的指標。

如果程式比較長,我們有時記不住 p 所指的記憶體是否已經被釋放,在繼續使用 p 之前,通常會用語句 if (p != NULL)進行防錯處理。

(1)指標消亡了,並不表示它所指的記憶體會被自動釋放。
(2)記憶體被釋放了,並不表示指標會消亡或者成了 NULL 指標

“野指標”的成因主要有兩種:
(1)指標變數沒有被初始化。任何指標變數剛被建立時不會自動成為 NULL 指標,它
的預設值是隨機的,它會亂指一氣。

(2)指標 p 被 free 或者 delete 之後,沒有置為 NULL,讓人誤以為 p 是個合法的指標。

(3)指標操作超越了變數的作用範圍。例如:

void Test(void)
{
  A *p;
  {
    A a;
    p = &a; // 注意 a 的生命期
  }
  p->Func(); // p 是“野指標”
}

 

光用 maloc/free 無法滿足動態對象的要求。對象在建立的同時要自動執行建構函式,對象在消亡之前要自動執行解構函式。由於
malloc/free 是庫函數而不是運算子,不在編譯器控制許可權之內,不能夠把執行建構函式和解構函式的任務強加於 malloc/free 。

因此 C++語言需要一個能完成動態記憶體分配和初始化工作的運算子 new,以及一個能完成清理與釋放記憶體工作的運算子 delete。

注意 new/delete 不是庫函數。

 

因為 C++程式經常要調用 C 函數,而 C 程式只能用 malloc/free 管理動態記憶體。故C++不把 malloc/free 淘汰。

 

 

記憶體耗盡怎麼辦

 

如果在申請動態記憶體時找不到足夠大的記憶體塊,malloc 和 new 將返回 NULL 指標,
宣告記憶體申請失敗。通常有三種方式處理“記憶體耗盡”問題。

 

(1)判斷指標是否為 NULL,如果是則馬上用 return 語句終止本函數。

(2)判斷指標是否為 NULL,如果是則馬上用 exit(1)終止整個程式的運行。

(3)為 new 和 malloc 設定異常處理函數。

 

54頁

 

C/C++ 記憶體管理問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.