C/C++ 程式記憶體布局分為五大區域,理解其特性對寫出高效、安全的程式至關重要。
| 區域 | 管理方式 | 儲存內容 | 生命週期 |
|---|---|---|---|
| 堆疊 | 編譯器自動分配/釋放 | 函數參數、區域變數、返回位址 | 函數呼叫期間 |
| 堆積 | 程式設計師手動管理 (new/delete, malloc/free) | 動態分配物件 | 手動控制,程式結束由 OS 回收 |
| 全域/靜態區 | 編譯器靜態分配 | 全域變數、static 變數 (已初始化/未初始化分區) | 程式全生命週期 |
| 常數區 | 編譯器分配,唯讀 | 字串常值、const 全域變數 | 程式全生命週期 |
| 程式碼區 | 編譯器分配,唯讀 | 函數機器碼 | 程式全生命週期 |
int g_init = 10; // 全域初始化區
int g_uninit; // 全域未初始化區 (BSS)
const char* g_str = "hello"; // 常數區 (字串), 指標在全域區
void Func() {
int a = 20; // 堆疊
static int s = 30; // 全域靜態區 (初始化)
char buf[] = "abc"; // 堆疊 (陣列內容複製自常數區)
char* p = "123"; // p 在堆疊, "123" 在常數區
char* q = new char[10]; // q 在堆疊, new 分配在堆積
delete[] q;
}
int a; 自動int* p = new int; 或 malloc 手動bad_alloc / 回傳 nullptrVirtualAlloc:直接保留位址空間,速度最快、最彈性,但使用最複雜char arr[] = "1234567890"; // 堆疊陣列 char* ptr = "1234567890"; // 指向常數區 char c1 = arr[1]; // 直接位址偏移: mov cl, [ebp-0Fh] char c2 = ptr[1]; // 間接: mov edx, [ebp-14h] / mov al, [edx+1]
堆疊陣列存取比指標間接存取快 (少一次載入指標值)。
高位址 +------------------+ | 堆積 | 向上增長 | (動態分配) | +------------------+ | ... | +------------------+ | 共用函式庫 | +------------------+ | ... | +------------------+ | 堆疊 | 向下增長 | (函數框架) | +------------------+ | 環境變數/參數 | +------------------+ 低位址
堆疊像去餐廳吃飯:點菜(申請)、吃(使用)、走人(釋放),全程服務好、快,但自由度低。
堆積像自己做菜:買食材、切菜、烹飪、洗碗,麻煩但自由度高、想吃什麼做什麼。
std::vector/std::string 等 RAII 容器)std::unique_ptr/shared_ptr 管理)new 對應 delete,new[] 對應 delete[]