c 動態記憶體管理

2022-08-27 21:00:11 字數 3734 閱讀 3042

1. 從靜態區分配,一般是全域性變數和static型別變數

2.從棧區分配記憶體,一般是區域性的變數,會隨著所在函式的結束而自動釋放

3.從堆中分配,一般是使用手動分配,使用malloc()函式和new來申請任意大小空間,不過要手動釋放空間,相應的使用free()函式和delete釋放,

如果不釋放該空間,而且指向該空間的指標指向了別的空間.則該空間就無法釋放,造成記憶體洩露,造成了記憶體浪費

1.在使用malloc()或new申請空間時,要檢查有沒有分配空間成功,判斷方法是判斷指標是否為null,如申請一塊很大的記憶體而沒有這麼大的記憶體則分配記憶體會失敗

2.申請成功後最好是將該記憶體清空,使用memset()後zeromemory()清空,不然存在垃圾而造成有時候輸出很大亂碼

3.不要忘記為陣列和動態記憶體賦初值。防止將未被初始化的記憶體作為右值使用。(這句話不太理解)

4.要防止陣列或指標記憶體越界,

5.申請記憶體成功後,使用結束後要釋放,系統不會自動釋放手動分配的記憶體

6.記憶體釋放後,指標還是指向那塊位址,不過這指標已經是"野指標"了,所以釋放記憶體後指標要指向null,不然很危險,容易出錯,if()對野指標的判斷不起作用

1. 陣列裡的資料可以單個修改,但指標的不行,如我的例子,char str = "hello",陣列的大小有6個字元(注意\0),可以通過str[0] = 'x'修改了的個字元,而指標

char *p = "word",p是指向了一串常量的字串,常量字串是不可修改的,如 p[0] = 'x',編譯器編譯時不會儲存,但執行時會出錯

2.內容的複製與比較

內容的複製要使用strcpy()函式,不要使用賦值符"=",內容的比較也是不要使用比較符號",==",使用strcmp()函式

[cpp]view plain

copy

// 陣列…  

char a = "hello";  

char b[10];  

strcpy(b, a);           // 不能用   b = a;  

if(strcmp(b, a) == 0)   // 不能用  if (b == a)  

[cpp]view plain

copy

// 指標…  

int len = strlen(a);  

char *p = (char *)malloc(sizeof(char)*(len+1));  

strcpy(p,a);            // 不要用 p = a;  

if(strcmp(p, a) == 0)   // 不要用 if (p == a)  

3,計算空間的大小

對陣列的計算是使用sizeof()函式,該函式會按照記憶體對齊的方式4的倍數計算,而指標的空間大小沒法計算,只能記住在申請空間時的空間大小

注意當陣列作為函式的引數進行傳遞時,該陣列自動退化為同型別的指標,不論陣列a的容量是多少,sizeof(a)始終等於sizeof(char *)

[cpp]view plain

copy

void func(char a[100])  

如果函式的引數是指標,則不要使用該引數來申請記憶體空間,這樣沒有實際的用處,而且這樣當函式結束時還得不到釋放記憶體而造成記憶體洩露

這個問題可以使用"指標的指標"的方法可以解決,不然使用返回指標位址的辦法,先看一下使用 "指標的指標"方法,

還可以考慮一下引用

使用返回記憶體位址的方法

使用返回的方式傳遞記憶體位址容易出錯的地方在於放回"棧記憶體"的指標,當getmemory()函式結束時棧記憶體也被釋放,

像這個**

[cpp]view plain

copy

char *getstring2(void)  

void test5(void)  

函式test5執行雖然不會出錯,但是函式getstring2的設計概念卻是錯誤的。因為getstring2內的「hello world」是常量字串,位於靜態儲存區,

它在程式生命期內恆定不變。無論什麼時候呼叫getstring2,它返回的始終是同乙個「唯讀」的記憶體塊。

1. 當我們使用free()和delete釋放一塊記憶體時,指標還是指向原來的位址,不過這時候的指標時野指標,

可以驗證一下.這圖是我除錯到if()語句時的情況,p還沒有指向null,只是釋放了p指向的空間了

執行的結果可以看看...

所以有這樣的一些特徵:

1.指標銷毀了,並不表示所指的空間也得到了釋放 :記憶體洩露

2.記憶體被釋放了,並不表示指標也被銷毀了或指向null :野指標

malloc與free是c++/c語言的標準庫函式,new/delete是c++的運算子。它們都可用於申請動態記憶體和釋放記憶體。對於非內部資料型別的物件而言,

光用maloc/free無法滿足動態物件的要求。物件在建立的同時要自動執行建構函式,物件在消亡之前要自動執行析構函式。由於malloc/free是庫函

數而不是運算子,不在編譯器控制許可權之內,不能夠把執行建構函式和析構函式的任務強加於malloc/free。

因此c++語言需要乙個能完成動態記憶體分配和初始化工作的運算子new,以及乙個能完成清理與釋放記憶體工作的運算子delete。注意new/delete不是庫函式。

我們先看一看malloc/free和new/delete如何實現物件的動態記憶體管理,看**

[cpp]view plain

copy

class obj  

~obj(void)  

void    initialize(void)  

void    destroy(void)  

};  

void usemallocfree(void)  

void usenewdelete(void)  

類obj的函式initialize模擬了建構函式的功能,函式destroy模擬了析構函式的功能。函式usemallocfree中,由於malloc/free不能執行建構函式與析構函式,必須呼叫成員函式initialize和destroy來完成初始化與清除工作。函式usenewdelete則簡單得多。

所以我們不要企圖用malloc/free來完成動態物件的記憶體管理,應該用new/delete。由於內部資料型別的「物件」沒有構造與析構的過程,對它們而言malloc/free和new/delete是等價的。

既然new/delete的功能完全覆蓋了malloc/free,為什麼c++不把malloc/free淘汰出局呢?這是因為c++程式經常要呼叫c函式,而c程式只能用malloc/free管理動態記憶體。

如果用free釋放「new建立的動態物件」,那麼該物件因無法執行析構函式而可能導致程式出錯。如果用delete釋放「malloc申請的動態記憶體」,理論上講程式不會出錯,但是該程式的可讀性很差。所以new/delete必須配對使用,malloc/free也一樣。

1.判斷指標是否為null,如果是則馬上用return語句終止本函式

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

3.為new和malloc設定異常處理函式。例如visual c++可以用_set_new_hander函式為new設定使用者自己定義的異常處理函式,

也可以讓malloc享用與new相同的異常處理函式

malloc()/free()和new/delete的使用要點網上有更詳細的說明

C 動態記憶體管理

我們都知道在c 中可以用new malloc動態分配記憶體空間,delete free釋放動態開闢的記憶體空間。1.那麼既然c 中有了可以動態開闢記憶體的函式為什麼又要有new delete呢?c 中的malloc free是繼承c語言中的malloc free,它的用法和在c語言中的用法一模一樣。...

C 動態記憶體管理

1 總結並剖析malloc free和new delete之間關係和差異。1 他們都是動態記憶體管理的入口 2 malloc要計算空間大小,返回值要強轉 new自動計算位元組大小,返回值是相應型別的指標 3 malloc只開闢空間 new開闢空間 呼叫建構函式初始化 delete呼叫析構函式清理 釋...

c 動態記憶體管理

c語言動態記憶體管理 c中關於動態記憶體的標準庫函式 malloc calloc realloc free 以下是關於這幾個函式的介紹 1 malloc 用於動態開闢記憶體 堆空間 返回型別為void 引數 size t size 是無符號整型表示要開闢的空間大小,單位是位元組,2 calloc 用...