2012軟考軟件設(shè)計(jì)師輔導(dǎo):C++內(nèi)存分配詳解

字號(hào):

一、關(guān)于內(nèi)存
    1、內(nèi)存分配方式
    內(nèi)存分配方式有三種:
    (1)從靜態(tài)存儲(chǔ)區(qū)域分配。內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。
    例如全局變量,static變量。
    (2)在棧上創(chuàng)建。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。
    (3)從堆上分配,亦稱(chēng)動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的時(shí)候用malloc或new申請(qǐng)任意多少的內(nèi)存,程序員自己負(fù)責(zé)在何時(shí)用free或delete釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期由我們決定,使用非常靈活,但問(wèn)題也最多。
    2、內(nèi)存使用錯(cuò)誤發(fā)生內(nèi)存錯(cuò)誤是件非常麻煩的事情。編譯器不能自動(dòng)發(fā)現(xiàn)這些錯(cuò)誤,通常是在程序運(yùn)行時(shí)才能捕捉到。而這些錯(cuò)誤大多沒(méi)有明顯的癥狀,時(shí)隱時(shí)現(xiàn),增加了改錯(cuò)的難度。有時(shí)用戶(hù)怒氣沖沖地把你找來(lái),程序卻沒(méi)有發(fā)生任何問(wèn)題,你一走,錯(cuò)誤又發(fā)作了。常見(jiàn)的內(nèi)存錯(cuò)誤及其對(duì)策如下:
    * 內(nèi)存分配未成功,卻使用了它。
    編程新手常犯這種錯(cuò)誤,因?yàn)樗麄儧](méi)有意識(shí)到內(nèi)存分配會(huì)不成功。常用解決辦法是,在使用內(nèi)存之前檢查指針是否為NULL.如果是用malloc或new來(lái)申請(qǐng)內(nèi)存,應(yīng)該用if(p==NULL) 或if(p!=NULL)進(jìn)行防錯(cuò)處理。
    * 內(nèi)存分配雖然成功,但是尚未初始化就引用它。
    犯這種錯(cuò)誤主要有兩個(gè)起因:一是沒(méi)有初始化的觀念;二是誤以為內(nèi)存的缺省初值全為零,導(dǎo)致引用初值錯(cuò)誤(例如數(shù)組)。內(nèi)存的缺省初值究竟是什么并沒(méi)有統(tǒng)一的標(biāo)準(zhǔn),盡管有些時(shí)候?yàn)榱阒担覀儗幙尚牌錈o(wú)不可信其有。所以無(wú)論用何種方式創(chuàng)建數(shù)組,都別忘了賦初值,即便是賦零值也不可省略,不要嫌麻煩。
    * 內(nèi)存分配成功并且已經(jīng)初始化,但操作越過(guò)了內(nèi)存的邊界。
    例如在使用數(shù)組時(shí)經(jīng)常發(fā)生下標(biāo)“多1”或者“少1”的操作。特別是在for循環(huán)語(yǔ)句中,循環(huán)次數(shù)很容易搞錯(cuò),導(dǎo)致數(shù)組操作越界。
    * 忘記了釋放內(nèi)存,造成內(nèi)存泄露。
    含有這種錯(cuò)誤的函數(shù)每被調(diào)用一次就丟失一塊內(nèi)存。剛開(kāi)始時(shí)系統(tǒng)的內(nèi)存充足,你看不到錯(cuò)誤。終有一次程序突然死掉,系統(tǒng)出現(xiàn)提示:內(nèi)存耗盡。
    動(dòng)態(tài)內(nèi)存的申請(qǐng)與釋放必須配對(duì),程序中malloc與free的使用次數(shù)一定要相同,否則肯定有錯(cuò)誤(new/delete同理)。
    * 釋放了內(nèi)存卻繼續(xù)使用它。
    有三種情況:
    (1)程序中的對(duì)象調(diào)用關(guān)系過(guò)于復(fù)雜,實(shí)在難以搞清楚某個(gè)對(duì)象究竟是否已經(jīng)釋放了內(nèi)存,此時(shí)應(yīng)該重新設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),從根本上解決對(duì)象管理的混亂局面。
    (2)函數(shù)的return語(yǔ)句寫(xiě)錯(cuò)了,注意不要返回指向“棧內(nèi)存”的“指針”或者“引用”,因?yàn)樵搩?nèi)存在函數(shù)體結(jié)束時(shí)被自動(dòng)銷(xiāo)毀。
    (3)使用free或delete釋放了內(nèi)存后,沒(méi)有將指針設(shè)置為NULL.導(dǎo)致產(chǎn)生“野指針”。
    「規(guī)則1」用malloc或new申請(qǐng)內(nèi)存之后,應(yīng)該立即檢查指針值是否為NULL.防止使用指針值為NULL的內(nèi)存。
    「規(guī)則2」不要忘記為數(shù)組和動(dòng)態(tài)內(nèi)存賦初值,防止將未被初始化的內(nèi)存作為右值使用。
    「規(guī)則3」避免數(shù)組或指針的下標(biāo)越界,特別要當(dāng)心發(fā)生“多1”或者“少1”操作。
    「規(guī)則4」動(dòng)態(tài)內(nèi)存的申請(qǐng)與釋放必須配對(duì),防止內(nèi)存泄漏。
    「規(guī)則5」用free或delete釋放了內(nèi)存之后,立即將指針設(shè)置為NULL,防止產(chǎn)生“野指針”。
    二、詳解new,malloc,GlobalAlloc
    1.new
    new和delete運(yùn)算符用于動(dòng)態(tài)分配和撤銷(xiāo)內(nèi)存的運(yùn)算符
    new用法:
    1>開(kāi)辟單變量地址空間
    1)new int; //開(kāi)辟一個(gè)存放數(shù)組的存儲(chǔ)空間,返回一個(gè)指向該存儲(chǔ)空間的地址。int *a = new int 即為將一個(gè)int類(lèi)型的地址賦值給整型指針a.
    2)int *a = new int(5) 作用同上,但是同時(shí)將整數(shù)賦值為5
    2>開(kāi)辟數(shù)組空間
    一維:int *a = new int[100];開(kāi)辟一個(gè)大小為100的整型數(shù)組空間
    一般用法: new 類(lèi)型 [初值]
    delete用法:
    1> int *a = new int;
    delete a; //釋放單個(gè)int的空間
    2>int *a = new int[5];
    delete [] a; //釋放int數(shù)組空間
    要訪(fǎng)問(wèn)new所開(kāi)辟的結(jié)構(gòu)體空間,無(wú)法直接通過(guò)變量名進(jìn)行,只能通過(guò)賦值的指針進(jìn)行訪(fǎng)問(wèn)。
    用new和delete可以動(dòng)態(tài)開(kāi)辟,撤銷(xiāo)地址空間。在編程序時(shí),若用完一個(gè)變量(一般是暫時(shí)存儲(chǔ)的數(shù)組),下次需要再用,但卻又想省去重新初始化的功夫,可以在每次開(kāi)始使用時(shí)開(kāi)辟一個(gè)空間,在用完后撤銷(xiāo)它。
    2. malloc原型:extern void *malloc(unsigned int num_bytes);用法:#i nclude 或#i nclude 功能:分配長(zhǎng)度為num_bytes字節(jié)的內(nèi)存塊說(shuō)明:如果分配成功則返回指向被分配內(nèi)存的指針,否則返回空指針NULL.當(dāng)內(nèi)存不再使用時(shí),應(yīng)使用free()函數(shù)將內(nèi)存塊釋放。
    malloc的語(yǔ)法是:指針名=(數(shù)據(jù)類(lèi)型*)malloc(長(zhǎng)度),(數(shù)據(jù)類(lèi)型*)表示指針。
    說(shuō)明:malloc 向系統(tǒng)申請(qǐng)分配指定size個(gè)字節(jié)的內(nèi)存空間。返回類(lèi)型是 void* 類(lèi)型。void* 表示未確定類(lèi)型的指針。C、C++規(guī)定,void* 類(lèi)型可以強(qiáng)制轉(zhuǎn)換為任何其它類(lèi)型的指針。
    malloc()函數(shù)的工作機(jī)制malloc函數(shù)的實(shí)質(zhì)體現(xiàn)在,它有一個(gè)將可用的內(nèi)存塊連接為一個(gè)長(zhǎng)長(zhǎng)的列表的所謂空閑鏈表。調(diào)用malloc函數(shù)時(shí),它沿連接表尋找一個(gè)大到足以滿(mǎn)足用戶(hù)請(qǐng)求所需要的內(nèi)存塊。然后,將該內(nèi)存塊一分為二(一塊的大小與用戶(hù)請(qǐng)求的大小相等,另一塊的大小就是剩下的字節(jié))。接下來(lái),將分配給用戶(hù)的那塊內(nèi)存?zhèn)鹘o用戶(hù),并將剩下的那塊(如果有的話(huà))返回到連接表上。調(diào)用free函數(shù)時(shí),它將用戶(hù)釋放的內(nèi)存塊連接到空閑鏈上。到最后,空閑鏈會(huì)被切成很多的小內(nèi)存片段,如果這時(shí)用戶(hù)申請(qǐng)一個(gè)大的內(nèi)存片段,那么空閑鏈上可能沒(méi)有可以滿(mǎn)足用戶(hù)要求的片段了。于是,malloc函數(shù)請(qǐng)求延時(shí),并開(kāi)始在空閑鏈上翻箱倒柜地檢查各內(nèi)存片段,對(duì)它們進(jìn)行整理,將相鄰的小空閑塊合并成較大的內(nèi)存塊。
    和new的不同從函數(shù)聲明上可以看出。malloc 和 new 至少有兩個(gè)不同: new 返回指定類(lèi)型的指針,并且可以自動(dòng)計(jì)算所需要大小。比如:int *p;p = new int; //返回類(lèi)型為int* 類(lèi)型(整數(shù)型指針),分配大小為 sizeof(int);或:int* parr;parr = new int [100]; //返回類(lèi)型為 int* 類(lèi)型(整數(shù)型指針),分配大小為 sizeof(int) * 100;而 malloc 則必須由我們計(jì)算要字節(jié)數(shù),并且在返回后強(qiáng)行轉(zhuǎn)換為實(shí)際類(lèi)型的指針。
    int* p;p = (int *) malloc (sizeof(int));第一、malloc 函數(shù)返回的是 void * 類(lèi)型,如果你寫(xiě)成:p = malloc (sizeof(int)); 則程序無(wú)法通過(guò)編譯,報(bào)錯(cuò):“不能將 void* 賦值給 int * 類(lèi)型變量”。所以必須通過(guò) (int *) 來(lái)將強(qiáng)制轉(zhuǎn)換。
    第二、函數(shù)的實(shí)參為 sizeof(int) ,用于指明一個(gè)整型數(shù)據(jù)需要的大小。如果你寫(xiě)成:int* p = (int *) malloc (1);代碼也能通過(guò)編譯,但事實(shí)上只分配了1個(gè)字節(jié)大小的內(nèi)存空間,當(dāng)你往里頭存入一個(gè)整數(shù),就會(huì)有3個(gè)字節(jié)無(wú)家可歸,而直接“住進(jìn)鄰居家”!造成的結(jié)果是后面的內(nèi)存中原有數(shù)據(jù)內(nèi)容全部被清空。
    3. GlobalAlloc
    VC中關(guān)于GlobalAlloc,GlobalLock,GlobalUnLock,GlobalFree調(diào)用GlobalAlloc函數(shù)分配一塊內(nèi)存,該函數(shù)會(huì)返回分配的內(nèi)存句柄。調(diào)用GlobalLock函數(shù)鎖定內(nèi)存塊,該函數(shù)接受一個(gè)內(nèi)存句柄作為參數(shù),然后返回一個(gè)指向被鎖定的內(nèi)存塊的指針。 您可以用該指針來(lái)讀寫(xiě)內(nèi)存。調(diào)用GlobalUnlock函數(shù)來(lái)解鎖先前被鎖定的內(nèi)存,該函數(shù)使得指向內(nèi)存塊的指針無(wú)效。調(diào)用GlobalFree函數(shù)來(lái)釋放內(nèi)存塊。您必須傳給該函數(shù)一個(gè)內(nèi)存句柄。
    GlobalAlloc說(shuō)明分配一個(gè)全局內(nèi)存塊返回值Long,返回全局內(nèi)存句柄。零表示失敗。會(huì)設(shè)置GetLastError參數(shù)表參數(shù) 類(lèi)型及說(shuō)明wFlags Long,對(duì)分配的內(nèi)存類(lèi)型進(jìn)行定義的常數(shù)標(biāo)志,如下所示:GMEM_FIXED 分配一個(gè)固定內(nèi)存塊GMEM_MOVEABLE 分配一個(gè)可移動(dòng)內(nèi)存塊GMEM_DISCARDABLE 分配一個(gè)可丟棄內(nèi)存塊GMEM_NOCOMPACT 堆在這個(gè)函數(shù)調(diào)用期間不進(jìn)行累積GMEM_NODISCARD 函數(shù)調(diào)用期間不丟棄任何內(nèi)存塊GMEM_ZEROINIT 新分配的內(nèi)存塊全部初始化成零dwBytes Long,要分配的字符數(shù)
    GlobalLock函數(shù)功能描述:鎖定一個(gè)全局的內(nèi)存對(duì)象,返回指向該對(duì)象的第一個(gè)字節(jié)的指針函數(shù)原型:LPVOID GlobalLock( HGLOBAL hMem )
    參數(shù):hMem:全局內(nèi)存對(duì)象的句柄。這個(gè)句柄是通過(guò)GlobalAlloc或GlobalReAlloc來(lái)得到的返回值:調(diào)用成功,返回指向該對(duì)象的第一個(gè)字節(jié)的指針調(diào)用失敗,返回NULL,可以用GetLastError來(lái)獲得出錯(cuò)信息注意:調(diào)用過(guò)GlobalLock鎖定一塊內(nèi)存區(qū)后,一定要調(diào)用GlobalUnlock來(lái)解鎖
    GlobalUnlock函數(shù)功能描述:解除被鎖定的全局內(nèi)存對(duì)象函數(shù)原型:BOOL GlobalUnlock( HGLOBAL hMem );參數(shù):hMem:全局內(nèi)存對(duì)象的句柄返回值:非零值,指定的內(nèi)存對(duì)象仍處于被鎖定狀態(tài)0,函數(shù)執(zhí)行出錯(cuò),可以用GetLastError來(lái)獲得出錯(cuò)信息,如果返回NO_ERROR,則表示內(nèi)存對(duì)象已經(jīng)解鎖了注意:這個(gè)函數(shù)實(shí)際上是將內(nèi)存對(duì)象的鎖定計(jì)數(shù)器減一,如果計(jì)數(shù)器不為0,則表示執(zhí)行過(guò)多個(gè)GlobalLock函數(shù)來(lái)對(duì)這個(gè)內(nèi)存對(duì)象加鎖,需要對(duì)應(yīng)數(shù)目的GlobalUnlock函數(shù)來(lái)解鎖。如果通過(guò)GetLastError函數(shù)返回錯(cuò)誤碼為ERROR_NOT_LOCKED,則表示未加鎖或已經(jīng)解鎖。
    示例:// Malloc memory hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, nSize);// Lock memory pMem = (BYTE *) GlobalLock(hMem);……
    // Unlock memory GlobalUnlock(hMem);GlobalFree(hMem);
    三 總結(jié)
    靈活自由是C/C++語(yǔ)言的一大特色,而這也為C/C++程序員出了一個(gè)難題。當(dāng)程序越來(lái)越復(fù)雜時(shí),內(nèi)存的管理也會(huì)變得越加復(fù)雜,稍有不慎就會(huì)出現(xiàn)內(nèi)存問(wèn) 題。內(nèi)存泄漏是最常見(jiàn)的內(nèi)存問(wèn)題之一。內(nèi)存泄漏如果不是很?chē)?yán)重,在短時(shí)間內(nèi)對(duì)程序不會(huì)有太大的影響,這也使得內(nèi)存泄漏問(wèn)題有很強(qiáng)的隱蔽性,不容易被發(fā)現(xiàn)。 然而不管內(nèi)存泄漏多么輕微,當(dāng)程序長(zhǎng)時(shí)間運(yùn)行時(shí),其破壞力是驚人的,從性能下降到內(nèi)存耗盡,甚至?xí)绊懙狡渌绦虻恼_\(yùn)行。另外內(nèi)存問(wèn)題的一個(gè)共同特點(diǎn) 是,內(nèi)存問(wèn)題本身并不會(huì)有很明顯的現(xiàn)象,當(dāng)有異?,F(xiàn)象出現(xiàn)時(shí)已時(shí)過(guò)境遷,其現(xiàn)場(chǎng)已非出現(xiàn)問(wèn)題時(shí)的現(xiàn)場(chǎng)了,這給調(diào)試內(nèi)存問(wèn)題帶來(lái)了很大的難度。
    下載Windows Debug 工具安裝后,使用其中的gflags.exe工具打開(kāi)PageHeap,gflags -p /enable MainD.exe /full重新使用VS用調(diào)試方式運(yùn)行,很快就找到了出錯(cuò)位置,因?yàn)樵谀硞€(gè)靜態(tài)函數(shù)中筆誤導(dǎo)致。在編寫(xiě)穩(wěn)定的服務(wù)器程序時(shí),這個(gè)工具尤為有用。
    1. 首先我們來(lái)看HeapAlloc:MSDN上的解釋為:HeapALloc是從堆上分配一塊內(nèi)存,且分配的內(nèi)存是不可移動(dòng)的(即如果沒(méi)有連續(xù)的空間能滿(mǎn)足分配的大小,程序不能將其他零散的空間利用起來(lái),從而導(dǎo)致分配失?。?,該分配方法是從一指定地址開(kāi)始分配,而不像GloabalAlloc是從全局堆上分配,這個(gè)有可能是全局,也有可能是 局部。函數(shù)原型為:LPVOID HeapAlloc(HANDLE hHeap,DWORD dwFlags,SIZE_T dwBytes);hHeap是進(jìn)程堆內(nèi)存開(kāi)始位置。
    dwFlags是分配堆內(nèi)存的標(biāo)志。包括HEAP_ZERO_MEMORY,即使分配的空間清零。dwBytes是分配堆內(nèi)存的大小。其對(duì)應(yīng)的釋放空間函數(shù)為HeapFree.
    2. 再看GlobalAlloc:該函數(shù)用于從全局堆中分配出內(nèi)存供程序使用,函數(shù)原型為:HGLOBAL GlobalAlloc(UINT uFlags,SIZE_T dwBytes);uFlags參數(shù)含義GHND GMEM_MOVEABLE和GMEM_ZEROINIT的組合GMEM_FIXED 分配固定內(nèi)存,返回值是一個(gè)指針GMEM_MOVEABLE 分配活動(dòng)內(nèi)存,在Win32中,內(nèi)存塊不能在物理內(nèi)存中移動(dòng),但能在默認(rèn)的堆中移動(dòng)。返回值是內(nèi)存對(duì)象的句柄,用函數(shù)GlobalLock可將句柄轉(zhuǎn)化為指針GMEM_ZEROINIT 將內(nèi)存內(nèi)容初始化為零GPTR GMEM_FIXED和GMEM_ZEROINIT的組合一般情況下我們?cè)诰幊痰臅r(shí)候,給應(yīng)用程序分配的內(nèi)存都是可以移動(dòng)的或者是可以丟棄的,這樣能使有限的內(nèi)存資源充分利用,所以,在某一個(gè)時(shí)候我們分配的那塊內(nèi)存的地址是不確定的,因?yàn)樗强梢砸苿?dòng)的,所以得先鎖定那塊內(nèi)存塊,這兒應(yīng)用程序需要調(diào)用API函數(shù)GlobalLock函數(shù)來(lái)鎖定句柄。如下: lpMem=GlobalLock(hMem); 這樣應(yīng)用程序才能存取這塊內(nèi)存。所以我們?cè)谑褂肎lobalAllock時(shí),通常搭配使用GlobalLock,當(dāng)然在不使用內(nèi)存時(shí),一定記得使用 GlobalUnlock,否則被鎖定的內(nèi)存塊一直不能被其他變量使用。
    GlobalAlloc對(duì)應(yīng)的釋放空間的函數(shù)為GlobalFree.
    3. LocalAlloc:該函數(shù)用于從局部堆中分配內(nèi)存供程序使用,函數(shù)原型為:HLOCAL LocalAlloc(UINT uFlags,SIZE_T uBytes);參數(shù)同GlobalAlloc.在16位Windows中是有區(qū)別的,因?yàn)樵?6位windows用一個(gè)全局堆和局部堆來(lái)管理內(nèi)存,每一個(gè)應(yīng)用程序或dll裝入內(nèi)存時(shí),代碼段被裝入全局 堆,而系統(tǒng)又為每個(gè)實(shí)例從全局堆中分配了一個(gè)64kb的數(shù)據(jù)段作為該實(shí)例的局部堆,用來(lái)存放應(yīng)用程序的堆棧和所有全局或靜態(tài)變量。而 LocalAlloc/GlobalAlloc就是分別用于在局部堆或全局堆中分配內(nèi)存。
    由于每個(gè)進(jìn)程的局部堆很小,所以在局部堆中分配內(nèi)存會(huì)受到空間的限制。但這個(gè)堆是每個(gè)進(jìn)程私有的,相對(duì)而言分配數(shù)據(jù)較安全,數(shù)據(jù)訪(fǎng)問(wèn)出錯(cuò)不至于影響到整個(gè)系統(tǒng)。而在全局堆中分配的內(nèi)存是為各個(gè)進(jìn)程共享的,每個(gè)進(jìn)程只要擁有這個(gè)內(nèi)存塊的句柄都可以訪(fǎng)問(wèn)這塊內(nèi)存,但是每個(gè)全局內(nèi)存空間需要額外的內(nèi)存開(kāi)銷(xiāo),造成分配浪費(fèi)。而且一旦發(fā)生嚴(yán)重錯(cuò)誤,可能會(huì)影響到整個(gè)系統(tǒng)的穩(wěn)定。
    不過(guò)在Win32中,每個(gè)進(jìn)程都只擁有一個(gè)省缺的私有堆,它只能被當(dāng)前進(jìn)程訪(fǎng)問(wèn)。應(yīng)用程序也不可能直接訪(fǎng)問(wèn)系統(tǒng)內(nèi)存。所以在Win32中全局堆和局部堆都指向進(jìn)程的省缺堆。用LocalAlloc/GlobalAlloc分配內(nèi)存沒(méi)有任何區(qū)別。甚至LocalAlloc分配的內(nèi)存可以被 GlobalFree釋放掉。所以在Win32下編程,無(wú)需注意Local和Global的區(qū)別,一般的內(nèi)存分配都等效于 HeapAlloc(GetProcessHeap(),……)。
    LocalAlloc對(duì)應(yīng)的釋放函數(shù)為L(zhǎng)ockFree.
    4. VirtualAlloc:該函數(shù)的功能是在調(diào)用進(jìn)程的虛地址空間,預(yù)定或者提交一部分頁(yè),如果用于內(nèi)存分配的話(huà),并且分配類(lèi)型未指定MEM_RESET,則系統(tǒng)將自動(dòng)設(shè)置為0;其函數(shù)原型:LPVOID VirtualAlloc(LPVOID lpAddress, // region to reserve or commit SIZE_T dwSize, // size of region DWORD flAllocationType, // type of allocation DWORD flProtect // type of access protection);VirtualAlloc可以通過(guò)并行多次調(diào)用提交一個(gè)區(qū)域的部分或全部來(lái)保留一個(gè)大的內(nèi)存區(qū)域。多重調(diào)用提交同一塊區(qū)域不會(huì)引起失敗。這使得一個(gè)應(yīng)用程 序保留內(nèi)存后可以隨意提交將被寫(xiě)的頁(yè)。當(dāng)這種方式不在有效的時(shí)候,它會(huì)釋放應(yīng)用程序通過(guò)檢測(cè)被保留頁(yè)的狀態(tài)看它是否在提交調(diào)用之前已經(jīng)被提交。
    VirtualAlloc對(duì)應(yīng)的釋放函數(shù)為VirtualFree.
    5.Malloc:malloc與free是C++/C語(yǔ)言的標(biāo)準(zhǔn)庫(kù)函數(shù),可用于申請(qǐng)動(dòng)態(tài)內(nèi)存和釋放內(nèi)存。對(duì)于非內(nèi)部數(shù)據(jù)類(lèi)型的對(duì)象而言,光用 malloc/free無(wú)法滿(mǎn)足動(dòng)態(tài)對(duì)象的要求。對(duì)象在創(chuàng)建的同時(shí)要自動(dòng)執(zhí)行構(gòu)造函數(shù),對(duì)象在消亡之前要自動(dòng)執(zhí)行析構(gòu)函數(shù)。由于malloc/free是 庫(kù)函數(shù)而不是運(yùn)算符,不在編譯器控制權(quán)限之內(nèi),不能夠把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強(qiáng)加于malloc/free.
    6.New:new/delete是C++的運(yùn)算符。可用于申請(qǐng)動(dòng)態(tài)內(nèi)存和釋放內(nèi)存。C++語(yǔ)言需要一個(gè)能完成動(dòng)態(tài)內(nèi)存分配和初始化工作的運(yùn)算符new, 以一個(gè)能完成清理與釋放內(nèi)存工作的運(yùn)算符delete.注意new/delete不是庫(kù)函數(shù)。C++程序經(jīng)常要調(diào)用C函數(shù),而C程序只能用malloc /free管理動(dòng)態(tài)內(nèi)存。new 是個(gè)操作符,和什么“+”,“-”,“=”……有一樣的地位。
    malloc是個(gè)分配內(nèi)存的函數(shù),供你調(diào)用的。
    new是保留字,不需要頭文件支持。
    malloc需要頭文件庫(kù)函數(shù)支持。new 建立的是一個(gè)對(duì)象,malloc分配的是一塊內(nèi)存。
    new建立的對(duì)象你可以把它當(dāng)成一個(gè)普通的對(duì)象,用成員函數(shù)訪(fǎng)問(wèn),不要直接訪(fǎng)問(wèn)它的地址空間malloc分配的是一塊內(nèi)存區(qū)域,就用指針訪(fǎng)問(wèn)好了,而且還可以在里面移動(dòng)指針。
    內(nèi)存泄漏對(duì)于malloc或者new都可以檢查出來(lái)的,區(qū)別在于new可以指明是那個(gè)文件的那一行,而malloc沒(méi)有這些信息。new可以認(rèn)為是malloc加構(gòu)造函數(shù)的執(zhí)行。new出來(lái)的指針是直接帶類(lèi)型信息的。而malloc返回的都是void指針。