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

C++ 內存分配五大區域詳解 - 堆、棧、自由存儲區、全局/靜態區、常量區

     編輯:關於C++

C++ 程序內存佈局五大區域

區域別名管理方式典型內容生命週期
棧Stack編譯器自動管理局部變量、函數參數、返回地址、寄存器保存隨作用域自動釋放
堆Heap程序員手動管理 (new/delete)動態分配對象手動釋放,程序結束由 OS 回收
自由存儲區Free Store程序員手動管理 (malloc/free)C 風格動態內存手動釋放,程序結束由 OS 回收
全局/靜態存儲區Data/BSS Segment編譯器/鏈接器管理全局變量、靜態變量 (static)程序啟動到結束
常量存儲區Literal Pool / .rodata只讀,編譯器管理字符串字面值、const 修飾的全局/靜態變量程序啟動到結束

詳細說明

1. 棧

  • 位於用戶虛擬地址空間高地址,向低地址增長
  • 函數調用時壓棧:返回地址、參數、局部變量、保存的寄存器
  • 函數返回時彈棧,自動銷毀局部對象(調用析構函數)
  • 大小有限(Linux 默認 8MB),棧溢出導致程序崩潰

2. 堆

  • C++ 特有術語,對應 new/delete、new[]/delete[]
  • 向高地址增長,非連續區域,由分配器管理空閒塊鏈表
  • 程序員負責配對釋放,忘記 delete 導致記憶體洩漏
  • 可動態擴展,受限於虛擬地址空間大小

3. 自由存儲區

  • C 語言術語,對應 malloc/free/realloc
  • 與堆在物理上通常是同一區域,但管理 API 不同
  • 嚴禁混用:new 必須配 delete,malloc 必須配 free
  • C++ 中 new 會調用構造函數,malloc 不會

4. 全局/靜態存儲區

  • 分為 .data 段(已初始化)和 .bss 段(未初始化,自動清零)
  • C++ 取消了 C 語言區分初始化/未初始化的區別,統一管理
  • static 修飾局部變量:存儲在這裡,但作用域限於函數內
  • 程序啟動時分配,結束時統一釋放

5. 常量存儲區

  • 存放字符串字面值("hello")、const 全局/靜態變量
  • 通常位於只讀內存頁(.rodata 段),寫入會觸發段錯誤
  • 字符串字面值可能被編譯器合併(相同字符串共用地址)

代碼驗證範例

#include 
using namespace std;

int global = 10;           // .data 段
static int s_global = 20;  // .data 段(內部鏈接)
const int c_global = 30;   // .rodata 段

void func() {
    int local = 1;         // 棧
    static int s_local = 2; // .data 段
    const int c_local = 3;  // 棧(非靜態 const 不進常量區)
    
    int* p1 = new int(4);   // 堆
    int* p2 = (int*)malloc(sizeof(int)); // 自由存儲區
    *p2 = 5;
    
    cout << "local: " << &local << endl;      // 高地址
    cout << "s_local: " << &s_local << endl;  // 低地址
    cout << "p1 (heap): " << p1 << endl;      // 中間地址
    cout << "p2 (free): " << p2 << endl;      // 中間地址
    cout << "global: " << &global << endl;    // 低地址
    cout << "literal: " << "hello" << endl;   // 只讀區
    
    delete p1; free(p2);
}

工程最佳實踐

  1. 優先使用棧/智能指針:std::vector, std::unique_ptr, std::shared_ptr 自動管理生命週期
  2. 避免裸指針 new/delete:易洩漏、易雙重釋放、異常不安全
  3. 大對象放堆:避免棧溢出
  4. 常量正確性:盡量用 const、constexpr,利用編譯器優化與只讀保護
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved