在程序運行過程中,操作系統會根據程序的需要,將內存劃分為多個功能不同的區段,以便更高效地管理內存資源和確保程序的穩定運行。不同的內存區段負責存儲不同類型的數據和代碼,涵蓋了從程序指令、全局變量到動態分配的數據等內容。

(內存分區圖示)
理解這些內存分區的結構和特性,不僅有助于編寫更高效的代碼,還能幫助排查和解決如段錯誤、內存泄漏、棧溢出等常見問題。以下是常見的六個主要內存分區的詳細解析:
01、棧區(Stack)
存儲內容:
函數參數(如 func(int a, int b) 中的 a 和 b)。局部變量(如函數內定義的 int x = 5;)。函數調用的上下文信息(如返回地址、寄存器備份)。
特性:
自動管理:變量生命周期與作用域綁定(如函數結束時自動釋放)。地址增長方向:向低地址擴展。高效但有限:分配速度快,但空間較小(默認幾 MB)。
典型問題:
棧溢出(如遞歸過深、超大局部數組 int arr[1000000];)。懸掛指針(返回局部變量地址)。
示例代碼:
voidfunc(){
intx=5; //局部變量,存儲在棧區
}
02、堆區(Heap)
存儲內容:動態分配的內存塊(如 malloc、calloc 分配的變量)。
特性:
手動管理:需通過 free 顯式釋放,否則導致內存泄漏。地址增長方向:向高地址擴展,與棧區相對生長。碎片問題:頻繁分配/釋放可能產生內存碎片,降低效率。
典型問題:
野指針(釋放后未置 NULL)。雙重釋放(free 同一指針多次)。
示例代碼:
int*arr=(int*)malloc(100*sizeof(int));
free(arr);
arr=NULL;//避免野指針
03、BSS段(Block Started by Symbol)
存儲內容:
未顯式初始化的全局變量(如 int g_uninit;)。未初始化的靜態變量(如 static int s_uninit;)。
特性:
隱式初始化:程序加載時由系統自動初始化為 0 或 NULL。節省空間:.bss 段不占用磁盤空間,僅在內存中分配。與 .data 區別:.data 存儲非零初始值,而 .bss 存儲默認零值。
示例代碼:
intg_uninit;//存儲在BSS段,自動初始化為0
staticints_uninit;//存儲在BSS段,自動初始化為0
04、數據段(Data Segment)
存儲內容:
已顯式初始化的全局變量(如 int g_var = 10;)。
已初始化的靜態變量(如函數內的 static int s_var = 20;)。
特性:
顯式初始化:必須賦初值(非零值)。
生命周期:從程序啟動到結束(與全局變量一致)。
示例:extern 聲明的全局變量實際指向此區。
示例代碼:
intg_var=10; //存儲在數據段
staticints_var=20;//存儲在數據段
05、常量區(Read-Only Data Segment)
存儲內容:
字符串常量(如 "Hello, World")。const 修飾的全局常量(如 const int MAX = 100;)。浮點數常量、整型常量表等只讀數據。
特性:
運行時不可修改:試圖修改會導致段錯誤(Segmentation Fault)。跨文件共享:同一常量在多個源文件中引用時,僅存儲一份。注意:const 修飾的局部變量不在此區,而是存儲在棧區。
示例代碼:
constintMAX=100;//存儲在常量區
char*msg="Hello";//存儲在常量區
06、代碼段(Text Segment)
存儲內容:編譯后的二進制機器指令(即程序的執行代碼)。
特性:
只讀:禁止修改,防止程序意外篡改指令。可共享:多個進程可同時加載同一份代碼(如動態庫)。示例:函數定義(如 void func() { ... })、控制邏輯(如 if/for 語句的底層實現)。
示例代碼:
voidfunc(){//函數定義存儲在代碼段
printf("Hello");
}
總結
| 區域 | 存儲內容 | 生命周期 | 常見問題 |
| 棧區 | 局部變量、參數、返回地址 | 函數調用期間 | 棧溢出、懸掛指針 |
| 堆區 | 動態分配的內存塊 | malloc 分配到 free 釋放 | 內存泄漏、野指針、雙重釋放 |
| BSS段 | 未初始化的全局和靜態變量 | 程序運行期間 | 無 |
| 數據段 | 已初始化的全局和靜態變量 | 程序運行期間 | 無 |
| 常量區 | 字符串常量、const 常量 | 程序運行期間 | 段錯誤 |
| 代碼段 | 機器指令 | 程序運行期間 | 段錯誤 |
-
內存
+關注
關注
9文章
3209瀏覽量
76358 -
操作系統
+關注
關注
37文章
7401瀏覽量
129282 -
C語言程序
+關注
關注
1文章
20瀏覽量
10606
發布評論請先 登錄
C語言使用函數調用的知識點
C語言程序編譯后內存地址的分配
快速搞懂C語言程序內存分區!
評論