記憶體管理學習筆記

2021-08-14 18:33:04 字數 3036 閱讀 5981

1.棧、堆和靜態區

靜態區:儲存自動全域性變數和static變數(包括全域性靜態變數和區域性靜態變數)。靜態區的內容在整個程式的生命週期內都存在。

棧:儲存區域性變數。棧上的內容只在函式的範圍內存在,當函式執行結束,這些內容也會自動被銷毀。其特點是效率高,但是空間大小有限。

堆:由malloc系列函式或new操作符分配的記憶體。其生命週期由free或delete決定。在沒有釋放之前一直存在,直到程式結束。其特點是使用靈活,空間比較大,但容易出錯。

2.常見的記憶體錯誤以及對策

2.1指標沒有指向一塊合法的記憶體

定義了指標變數,但是沒有為指標分配記憶體,即指標沒有指向一塊合法的記憶體。

2.1.1結構體成員指標未初始化

struct studentstu,*pstu;

int main(void)

定義了結構體變數stu,但是它沒有想到這個結構體內部char * name這個成員在定義結構體變數stu時,只是給name這個指標變數本身分配了4個位元組。name指標並沒有指向乙個合法的位址,這時候其內部存的只是一些亂碼。所在在呼叫strcpy函式時,會出現段錯誤。

解決辦法是需要name分配空間。

struct studentstu,*pstu;

int main(void)

上面也是只給pstu分配了空間,而沒有給name分配空間,同樣會出現錯誤。

正確的例項:

struct studentstu,*pstu;

int main(void)

2.1.2 沒有為結構體指標分配足夠的記憶體

struct studentstu,*pstu;

int main(void)

為pstu分配記憶體的時候,分配的記憶體大小不合適。這裡把sizeof(struct student)誤寫為sizeof(struct student *),當然name也沒有被分配空間,拷貝的時候肯定會出錯。

2.1.3 函式的入口校驗

不管什麼時候,我們使用指標之前一定要確保指標是有效的。

2.2 為指標分配的記憶體太小

為指標分配了記憶體,但是記憶體大小不夠,代指出現越界錯誤。

char *p1 = "abcdgeg";

char *p2 = (char *)malloc(sizeof(char)*strlen(p1));

strcpy(p2,p1);

p1是字串常量,其長度是7個字元,但其所佔記憶體大小為8個byte。字串常量的結束標誌是'\0'。這樣的話,將導致p1字串常量最後乙個空字元沒有被拷貝到p2中,解決的辦法是加上這個字串結束標誌符。
char *p2 = (char *)malloc(sizeof(char)*strlen(p1) + 1*sizeof(char));

注意:只有字串常量才有結束標誌符。

2.3 記憶體分配成功,但並未初始化

int i=10;

char *p = (char*)malloc(sizeof(char));

在我們還不確定這個變數的初值時,可以將其初始化為0或者null。

int i=0;

char *p = null;

定義了陣列的話,可以這樣初始化:

int a[10] = ;
或者使用memset函式,memset(a,0,sizeof(a));
如果指標變數未被初始化,會導致if語句或者assert語句校驗失敗。

2.4 記憶體越界

記憶體分配成功,且已經初始化,但是操縱越過了記憶體的邊界。

2.5記憶體洩露

記憶體洩露是很難避免的。會產生洩露的記憶體就是堆上的記憶體,也就是由malloc系列函式分配的記憶體。如果用完沒有及時free或

delete,這塊記憶體就無法釋放,知道整個程式終止。

2.5.1如果使用malloc

(void *)malloc(int size);

malloc函式的返回值是乙個void型別的指標,引數為int型別資料,即申請分配的記憶體大小,單位是byte。記憶體分配成功之後,

malloc函式返回這塊記憶體的首位址。你需要乙個指標來接收這個位址。但是由於malloc返回值是void*型別的,所以必須強制轉換成

你所接收的型別。也就是說這塊記憶體將要用來儲存什麼型別的資料。

分配完成之後需要檢驗是否分配成功。

if(null != p)

2.5.2 記憶體釋放

free(p);

free函式就做了一件事:斬斷指標變數與這塊記憶體的關係。

我們可以說malloc函式分配的記憶體塊是屬於p的,因為我們對這塊記憶體的訪問都需要通過p來進行。free函式就是把這塊內

存和p之間的所有關係斬斷。從此p和哪塊記憶體之間的所有關係斬斷。至於指標變數p本身儲存的位址並沒有改變,但是它對這個位址

處的哪塊記憶體卻已經沒有所有權了。那塊被釋放的記憶體裡面儲存的值也沒有改變,只是再也沒有辦法使用了。

malloc與free配對使用,不然肯定出錯。

2.5.3記憶體釋放之後

既然free函式之後指標變數p本身儲存的位址並沒有改變,哪我們就需要重新把p的值變為null;

釋放完了指標,一定要設定指標為null。

2.5.4 記憶體已經被釋放了,但是繼續通過指標來使用

一般有三種情況:

1.就是free(p)之後,繼續通過p指標來訪問記憶體。解決辦法就是給p設定為null。

2.函式返回棧記憶體。比如在函式內部定義了乙個陣列,卻用return語句返回指向該陣列的指標。

3.記憶體使用太複雜,弄不清哪塊記憶體被釋放了,哪塊記憶體沒有被釋放。解決的辦法是重新設計程式,改善物件之間的呼叫關係。

object c 記憶體管理學習筆記

nsautoreleasepool pool nsautoreleasepool alloc init pool drain 這個函式可以把autoreleasepool裡的物件釋放 在for迴圈中每次都釋放記憶體池的示例 nsautoreleasepool temppool for i 0 i a...

effectiveC 記憶體管理 學習筆記

1.盡量使用初始化列表而不要再建構函式裡賦值,初始化順序和宣告的順序一致,一些型別如const,引用等,必須使用初始化。對於非內部資料型別成員物件應當採用初始化表,以獲取更高的效率。example b b const a a m a a 只呼叫了類a的拷貝建構函式 2.基類都使用虛析構函式,這樣才能...

記憶體管理學習筆記1

背景 乙個人想要遛狗,中途可以換別的狗遛 所以首先得有乙個狗的類 dog 然後乙個 person類 裡有乙個dog的變數,自己過載setdog函式 synthsize dog dog void setdog dog adog if dog adog 先判斷要設定的狗是不是原來的狗,避免誤設定同一條狗...