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*是指向一個常量,做用域爲函數內部,被分配在程序的常量區,直到整個程序結束才被銷燬,因此在程序結束前常量仍是存在的。而第二個是數組存放的,做用域爲函數內部,被分配在棧中,就會在函數調用結束後被釋放掉,這時你再調用,確定就錯誤了。優化

內存分配

  什麼是局部變量、全局變量和靜態變量?spa

  顧名思義,局部變量就是在一個有限的範圍內的變量,做用域是有限的,對於程序來講,在一個函數體內部聲明的普通變量都是局部變量,局部變量會在棧上申請空間,函數結束後,申請的空間會自動釋放。而全局變量是在函數體外申請的,會被存放在全局(靜態區)上,知道程序結束後纔會被結束,這樣它的做用域就是整個程序。靜態變量和全局變量的存儲方式相同,在函數體內聲明爲static就可使此變量像全局變量同樣使用,不用擔憂函數結束而被釋放。.net

相關函數:

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(在棧上申請內存,自動釋放)等。code

相關文章
相關標籤/搜索