C語言中的記憶體分配與釋放 對C語言一直都是抱著學習的態度,很多都不懂,今天突然被問道C語言的記憶體分配問題,說了一些自己知道的,但感覺回答的並不完善,所以才有這篇筆記,總結一下C語言中記憶體分配的主要內容。 相關問題 剛剛在一篇博文看到一個簡單的問題: 兩段代碼都很簡單,輸出一段字元,類型不同,一個是c ...
C語言中的記憶體分配與釋放
對C語言一直都是抱著學習的態度,很多都不懂,今天突然被問道C語言的記憶體分配問題,說了一些自己知道的,但感覺回答的並不完善,所以才有這篇筆記,總結一下C語言中記憶體分配的主要內容。
相關問題
剛剛在一篇博文看到一個簡單的問題:
//code1 char* toStr() { char *s = "abcdefghijkl"; return s; } int main() { cout << toStr() << endl; return 0; } //code2 char* toStr() { char s[] = "abcdefghijkl"; return s; } int main() { cout << toStr() << endl; return 0; }
兩段代碼都很簡單,輸出一段字元,類型不同,一個是char*字元串,一個是char[]數據。
結果你知道嗎? 這個我確實知道,相信大部分人也都回知道,必然有一個不好使,或者兩個都不好使!!!都對就沒意思了~
結果:第一個正確輸出,第二個輸出亂碼。
原因:在於局部變數的作用域和記憶體分配的問題,第一char*是指向一個常量,作用域為函數內部,被分配在程式的常量區,直到整個程式結束才被銷毀,所以在程式結束前常量還是存在的。而第二個是數組存放的,作用域為函數內部,被分配在棧中,就會在函數調用結束後被釋放掉,這時你再調用,肯定就錯誤了。
記憶體分配
什麼是局部變數、全局變數和靜態變數?
顧名思義,局部變數就是在一個有限的範圍內的變數,作用域是有限的,對於程式來說,在一個函數體內部聲明的普通變數都是局部變數,局部變數會在棧上申請空間,函數結束後,申請的空間會自動釋放。而全局變數是在函數體外申請的,會被存放在全局(靜態區)上,知道程式結束後才會被結束,這樣它的作用域就是整個程式。靜態變數和全局變數的存儲方式相同,在函數體內聲明為static就可以使此變數像全局變數一樣使用,不用擔心函數結束而被釋放。
相關函數:
void *malloc(size_t size); void free(void *p); /*一般這樣用 Struct elem *p; p = (struct elem*)malloc(sizeof(struct elem)) void free(p) */
malloc原理
malloc函數的實質體現在,它有一個將可用的記憶體塊連接為一個長長的列表的所謂空閑鏈表。調用malloc函數時,它沿連接表尋找一個大到足以滿足用戶請求所需要的記憶體塊。然後,將該記憶體塊一分為二(一塊的大小與用戶請求的大小相等,另一塊的大小就是剩下的位元組)。接下來,將分配給用戶的那塊記憶體傳給用戶,並將剩下的那塊(如果有的話)返回到連接表上。調用free函數時,它將用戶釋放的記憶體塊連接到空閑鏈上。到最後,空閑鏈會被切成很多的小記憶體片段,如果這時用戶申請一個大的記憶體片段,那麼空閑鏈上可能沒有可以滿足用戶要求的片段了。於是,malloc函數請求延時,並開始在空閑鏈上翻箱倒櫃地檢查各記憶體片段,對它們進行整理,將相鄰的小空閑塊合併成較大的記憶體塊。如果無法獲得符合要求的記憶體塊,malloc函數會返回NULL指針,因此在調用malloc動態申請記憶體塊時,一定要進行返回值的判斷。
分類:
- 棧區(stack)—由編譯器自動分配釋放,存放函數的參數值,局部變數的值等。其操作方式類似於數據結構中的棧。
- 堆區(heap)—一般由程式員分配釋放,若程式員不釋放,程式結束時可能由OS回收。註意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表
- 全局區(靜態區)(static)—全局變數和靜態變數的存儲是放在一塊的,初始化的全局變數和靜態變數在一塊區域,未初始化的全局變數和未初始化的靜態 變數在相鄰的另一塊區域。 程式結束後由系統釋放。
- 常量區—常量字元串就是放在這裡的,直到程式結束後由系統釋放。上面的問題就在這裡!!!
- 代碼區—存放函數體的二進位代碼。
直接搬運的代碼,確實很好!!容易理解
//main.cpp int a = 0; //全局初始化區 char *p1; //全局未初始化區 main() { int b; //棧 char s[] = "abc"; //棧 char *p2; //棧 char *p3 = "123456"; //123456\\0在常量區,p3在棧上。 static int c =0;//全局(靜態)初始化區 p1 = (char *)malloc(10); p2 = (char *)malloc(20);//分配得來得10和20位元組的區域就在堆區。 strcpy(p1, "123456"); //123456\\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。 }
此外,還有realloc(重新分配記憶體)、calloc(初始化為0)、alloca(在棧上申請記憶體,自動釋放)等。
本文 由 cococo點點 創作,採用 知識共用 署名-非商業性使用-相同方式共用 3.0 中國大陸 許可協議進行許可。歡迎轉載,請註明出處:
轉載自:cococo點點 htt