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