首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C/C++ 記憶體佈局:堆與棧的本質區別深度解析

     編輯:關於C語言

程式記憶體五大區

  1. 棧區:編譯器自動管理,存函數參數、區域變量,LIFO,向低址增長。
  2. 堆區:程序員手動 malloc/free 或 new/delete,向高址增長,非連續。
  3. 全局/靜態區:全域變量、static 變量。初始化與未初始化分段。
  4. 常量區:字符串字面值等唯讀數據。
  5. 代碼區:函數二進位機器碼。

代碼直觀示例

int a = 0;           // 全局初始化區
char *p1;            // 全局未初始化區

int main() {
    int b;           // 棧
    char s[] = "abc";// 棧(陣列內容複製至此)
    char *p2;        // 棧
    char *p3 = "123456"; // "123456" 在常量區,p3 在棧
    static int c = 0; // 全局靜態初始化區
    p1 = malloc(10);  // 10 bytes 在堆
    p2 = malloc(20);  // 20 bytes 在堆
    strcpy(p1, "123456"); // 複製到堆,常量區可能合併優化
}

核心差異對比

維度棧堆
分配方式編譯器自動程序員手動
釋放方式自動(函數返回)手動(free/delete)
空間大小固定(Win 預設 1-2MB)受限於虛擬記憶體,極大
生長方向向低地址向高地址
碎片問題無易產生碎片
分配速度極快(指針移動)較慢(鏈表遍歷)
存取效率高(連續、熱點在缓存)較低(間接寻址)

棧幀內容與調用慣例

函數調用時入棧順序:

  1. 返回地址(下一條指令)
  2. 參數(右→左壓棧)
  3. 舊 ebp(建立棧幀鏈)
  4. 區域變量

返回時逆序出棧,恢復 esp/ebp,跳回返回地址。

堆管理機制

  • OS 維護空閒塊鏈表
  • 分配:首次適配,分割多餘塊回鏈表
  • 塊頭記錄大小,供 free 精確釋放

存取效率實測

char c[] = "1234567890";  // 棧上陣列
char *p = "1234567890";   // 指向常量區

a = c[1];  // 反組譯:mov cl, [ebp-0Fh]  → 直接索引
a = p[1];  // 反組譯:mov edx, [ebp-14h]; mov al, [edx+1] → 間接兩步

棧上陣列直接偏移寻址,指針需先取指針值再偏移,指令更多、更慢。

經典比喻

  • 棧 = 餐廳吃飯:點菜(申請)→吃(用)→走人(自動清理),快但自由度低。
  • 堆 = 自己做飯:買菜、洗菜、做、洗碗全自己管,麻煩但自由度高。

概念辨析

文中「堆/棧」指作業系統記憶體管理區域,與數據結構中的堆(優先隊列)、棧(LIFO 結構)是完全不同的兩組概念。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved