C++ 內存、new與malloc分配內存區別?


 一關於內存
 1、內存分配方式
  內存分配方式有三種:
  (1)從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在
。例如全局變量,static變量。
  (2)在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存
儲單元自動被釋放。棧內存分配運算內置於處理器的指令集中,效率很高,但是分配的內存容量有限。
  (3) 從堆上分配,亦稱動態內存分配。程序在運行的時候用malloc或new申請任意多少的內存,程序員自
己負責在何時用free或delete釋放內存。動態內存的生存期由我們決定,使用非常靈活,但問題也最多。
   2.內存使用錯誤
      發生內存錯誤是件非常麻煩的事情。編譯器不能自動發現這些錯誤,通常是在程序運行時才能捕捉到。
而這些錯誤大多沒有明顯的症狀,時隱時現,增加了改錯的難度。有時用戶怒氣沖沖地把你找來,程序卻沒
發生任何問題,你一走,錯誤又發作了。 常見的內存錯誤及其對策如下:
       * 內存分配未成功,卻使用了它。
  編程新手常犯這種錯誤,因為他們沒有意識到內存分配會不成功。常用解決辦法是,在使用內存之前檢查
指針是否為NULL。如果是用malloc或new來申請內存,應該用if(p==NULL) 或if(p!=NULL)進行防錯處理。
  * 內存分配雖然成功,但是尚未初始化就引用它。
  犯這種錯誤主要有兩個起因:一是沒有初始化的觀念;二是誤以為內存的缺省初值全為零,導致引用初值
錯誤(例如數組)。 內存的缺省初值究竟是什么並沒有統一的標准,盡管有些時候為零值,我們寧可信其無不
可信其有。所以無論用何種方式創建數組,都別忘了賦初值,即便是賦零值也不可省略,不要嫌麻煩。
  * 內存分配成功並且已經初始化,但操作越過了內存的邊界。

  例如在使用數組時經常發生下標“多1”或者“少1”的操作。特別是在for循環語句中,循環次數很容易搞
錯,導致數組操作越界。

  * 忘記了釋放內存,造成內存泄露。

  含有這種錯誤的函數每被調用一次就丟失一塊內存。剛開始時系統的內存充足,你看不到錯誤。終有一次

程序突然死掉,系統出現提示:內存耗盡。

  動態內存的申請與釋放必須配對,程序中malloc與free的使用次數一定要相同,否則肯定有錯誤

(new/delete同理)。

  * 釋放了內存卻繼續使用它。
 
  有三種情況:

  (1)程序中的對象調用關系過於復雜,實在難以搞清楚某個對象究竟是否已經釋放了內存,此時應該重新

設計數據結構,從根本上解決對象管理的混亂局面。

  (2)函數的return語句寫錯了,注意不要返回指向“棧內存”的“指針”或者“引用”,因為該內存在函

數體結束時被自動銷毀。

  (3)使用free或delete釋放了內存后,沒有將指針設置為NULL。導致產生“野指針”。

  【規則1】用malloc或new申請內存之后,應該立即檢查指針值是否為NULL。防止使用指針值為NULL的內存

  【規則2】不要忘記為數組和動態內存賦初值。防止將未被初始化的內存作為右值使用。

  【規則3】避免數組或指針的下標越界,特別要當心發生“多1”或者“少1”操作。

  【規則4】動態內存的申請與釋放必須配對,防止內存泄漏。

  【規則5】用free或delete釋放了內存之后,立即將指針設置為NULL,防止產生“野指針”。

二. 詳解new,malloc,GlobalAlloc
 1.  new

  new和delete運算符用於動態分配和撤銷內存的運算符

new用法:

          1>     開辟單變量地址空間

               1)new int;  //開辟一個存放數組的存儲空間,返回一個指向該存儲空間的地址.int *a = new

int 即為將一個int類型的地址賦值給整型指針a. 

               2)int *a = new int(5) 作用同上,但是同時將整數賦值為5

          2>    開辟數組空間

               一維: int *a = new int[100];開辟一個大小為100的整型數組空間

         一般用法: new 類型 [初值]

delete用法:

          1> int *a = new int;

               delete a;   //釋放單個int的空間

          2>int *a = new int[5];

               delete [] a; //釋放int數組空間

          要訪問new所開辟的結構體空間,無法直接通過變量名進行,只能通過賦值的指針進行訪問.

          用new和delete可以動態開辟,撤銷地址空間.在編程序時,若用完一個變量(一般是暫時存儲的數組),

下次需要再用,但卻又想省去重新初始化的功夫,可以在每次開始使用時開辟一個空間,在用完后撤銷它.

2.  malloc
  原型:extern void *malloc(unsigned int num_bytes); 
  用法:#i nclude <malloc.h>或#i nclude <stdlib.h> 
  功能:分配長度為num_bytes字節的內存塊 
  說明:如果分配成功則返回指向被分配內存的指針,否則返回空指針NULL。 
  當內存不再使用時,應使用free()函數將內存塊釋放。 
  malloc的語法是:指針名=(數據類型*)malloc(長度),(數據類型*)表示指針. 
說明:malloc 向系統申請分配指定size個字節的內存空間。返回類型是 void* 類型。void* 表示未確定類型

的指針。C,C++規定,void* 類型可以強制轉換為任何其它類型的指針。

malloc()函數的工作機制 
  malloc函數的實質體現在,它有一個將可用的內存塊連接為一個長長的列表的所謂空閑鏈表。調用malloc

函數時,它沿連接表尋找一個大到足以滿足用戶請求所需要的內存塊。然后,將該內存塊一分為二(一塊的大

小與用戶請求的大小相等,另一塊的大小就是剩下的字節)。接下來,將分配給用戶的那塊內存傳給用戶,並

將剩下的那塊(如果有的話)返回到連接表上。調用free函數時,它將用戶釋放的內存塊連接到空閑鏈上。到

最后,空閑鏈會被切成很多的小內存片段,如果這時用戶申請一個大的內存片段,那么空閑鏈上可能沒有可以

滿足用戶要求的片段了。於是,malloc函數請求延時,並開始在空閑鏈上翻箱倒櫃地檢查各內存片段,對它們

進行整理,將相鄰的小空閑塊合並成較大的內存塊。
 
和new的不同
從函數聲明上可以看出。malloc 和 new 至少有兩個不同: new 返回指定類型的指針,並且可以自動計算所需

要大小。比如:
int *p;
p = new int; //返回類型為int* 類型(整數型指針),分配大小為 sizeof(int);
或:
int* parr;
parr = new int [100]; //返回類型為 int* 類型(整數型指針),分配大小為 sizeof(int) * 100;
而 malloc 則必須由我們計算要字節數,並且在返回后強行轉換為實際類型的指針。
int* p;
p = (int *) malloc (sizeof(int));
第一、malloc 函數返回的是 void * 類型,如果你寫成:p = malloc (sizeof(int)); 則程序無法通過編譯,

報錯:“不能將 void* 賦值給 int * 類型變量”。所以必須通過 (int *) 來將強制轉換。
第二、函數的實參為 sizeof(int) ,用於指明一個整型數據需要的大小。如果你寫成:
int* p = (int *) malloc (1);
代碼也能通過編譯,但事實上只分配了1個字節大小的內存空間,當你往里頭存入一個整數,就會有3個字節無

家可歸,而直接“住進鄰居家”!造成的結果是后面的內存中原有數據內容全部被清空。

三 new malloc 區別

1、malloc與free是C++/C語言的標准庫函數,new/delete是C++的運算符。它們都可用於申請動態內存和釋放內存。
2、new 不止是分配內存,而且會調用類的構造函數,同理delete會調用類的析構函數,而malloc則只分配內存,不會進行初始化類成員的工作,同樣free也不會調用析構函數
3、內存泄漏對於malloc或者new都可以檢查出來的,區別在於new可以指明是那個文件的那一行,而malloc沒有這些信息。
4、new 和 malloc效率比較
new可以認為是malloc加構造函數的執行。
new出來的指針是直接帶類型信息的。
而malloc返回的都是void指針

參考 http://www.cnblogs.com/fujinliang/archive/2012/10/12/2721624.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM