C中存儲分區詳解


 

一. 在c中分為這幾個存儲區:棧(stack),堆(heap),代碼段(text),數據段(data),bss 段,常量存儲區,
1.棧(stack):由編譯器自動分配釋放
自動分配,自動回收:棧區里面存放的是局部變量;在定義局部變量的時候,系統在棧區自動分配內存,在結束時,自動回收內存;
臟內存:棧區每次使用之前需要對棧區進行初始化;對於定義局部變量時,需要對局部變量進行初始化;
臨時性:(函數不能返回棧變量的指針,因為這個空間是臨時的)
反復使用:棧內存在程序中其實就是那一塊空間,程序反復使用這一塊空間。
棧的大小有限,因此 會出現棧溢出

2.堆(heap): 一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收
手動分配:malloc分配內存,free進行釋放內存;
臟內存:堆區每次使用之前呢需要對堆區進行初始化;
臨時性:堆區每次分配的內存釋放之后,就不能在使用;
malloc的使用:malloc每次分配的內存之后需要進行對其返回指針為void *類型,需要進行強制類型轉換,並對返回指針進行檢查是否為null;
malloc和free為c語言的標准庫函數,不能分配對象;
內存泄漏;
gcc中的malloc默認最小是以16B為分配單元的;如果malloc小於16B的大小時都會返 回一個16字節的大小的內存。

3.代碼段(text):

  也叫文本段,代碼段其實就是函數編譯后生成的東西;

4.數據段(data):

  也被稱為數據區、靜態數據區、靜態區;
c語言中
1.顯示初始化為非零全局變量
2.顯示初始化為非零的靜態局部變量存儲在這個段;

5.bss 段(又叫:ZI(zero initial)段):.bss 段
c語言中
1).顯示初始化為0的全局變量;

2).未初始化的全局變量存儲在這個段。--零初始化段;

3).顯示初始化為0的static局部變量;

4).未初始化的static局部變量存儲在這個段;

 

6.自定義段:

  段名由程序員自己定義,段的屬性和特征也由程序員自己定義。

7.常量存儲區:

  一塊比較特殊的存儲區,存放的是常量,不允許修改(當然,你要通過非正當手段也可以修改)

8.文件映射區:

  進程打開了文件后,將這個文件的內容從硬盤讀到進程的文件映射區,以后就直接在內存中操作這個 文件,讀寫完了后在保存時再將內存中的文件寫到硬盤中去。

9.內核映射區:

  內核映射區就是將操作系統內核程序映射到這個區域了。

10.不同的存儲方式有不同的特點,簡單總結如下:
1)函數內部臨時使用,出了函數不會用到,就定義局部變量
2)堆內存和數據段幾乎擁有完全相同的屬性,大部分時候是可以完全替換的。

  生命周期不一樣:

    堆內存的生命周期是從malloc開始到free結束;

    全局變量是從整個程序一開始執行就開始,直到整個程序結束才會消滅,伴隨程序運行的一生。

  啟示:如果變量只是在程序的一個階段有用,用完就不用了,就適合用堆內存;

     如果這個變量本身和程序是一生相伴的,那就適合用全局變量。

補充1:
1)所有未初始化的靜態(static)變量和全局變量,編譯器會默認賦初值0。
2)程序在加載到內存前,代碼區(text)和全局區(data和bss)的大小就是固定的,程序運行期間不能改變。
3)data段和bss區中的數據的生存周期為整個程序運行過程。
4)data段、text區和bss區是由編譯器在編譯時分配的,堆和棧是由系統在運行時分配的。

12.生命周期/作用域:
1).生命周期:指變量活着或者說是存在的時間;
2).作用域:指可以使用這個變量的范圍;

 

結合示例詳解:

 

#define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <stdio.h> #include <string.h>

int c = 1;              //初始化為非零的全局變量:.data段
int a = 0;           //初始化為0的全局變量:.bss段
char *p1;             //未初始化的全局變量:.bss段
void main() {   int b;            //局部變量:stack(棧)
  char s[] = "abc";      //局部變量:stack(棧)
  char *p2;           //局部變量:stack(棧)
  char *p3 = "123456";    //字符串"123456"在常量區,p3局部變量:stack(棧)
  static int c = 0;      //顯示初始化的局部變量:.bss段
  p1 = (char *)malloc(10);  //malloc分配的內存:heap(堆)
  strcpy(p1, "123456");   system("pause");   return; }

補充2:

明確區分堆與棧:
在bbs上,堆與棧的區分問題,似乎是一個永恆的話題,由此可見,初學者對此往往是混淆不清的,所以我決定拿他第一個開刀。
首先,我們舉一個例子:

void func()
{ 
int* p=new int[5];    //包含了堆與棧
}

new分配了一塊堆內存;
局部變量指針變量p分配的是一塊棧內存;
意義:在棧內存中存放了一個指向一塊堆內存的指針p。在程序會先確定在堆中分配內存的大小,然后調用operator new分配內存,然后返回這塊內存的首地址,放入棧中。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM