記憶體配置錯誤是 C/C++ 程式崩潰、記憶體洩漏、安全性漏洞的首要根因。理解堆疊與堆的差異、生命週期、配置機制,是寫出健壯、高效能程式的基石。
| 區域 | 內容 | 管理方式 | 生命週期 |
|---|---|---|---|
| 程式碼區 | 函式二進位機器碼 | 編譯器/連結器 | 程式執行期間 |
| 文字常數區 | 字串常值 (如 "hello") | 系統 | 程式結束釋放 |
| 全域/靜態區 | 全域變數、static 變數 | 系統 | 程式結束釋放 |
| 堆疊 | 函式參數、區域變數、回傳位址 | 編譯器自動管理 | 函式呼叫/返回 |
| 堆 | 動態配置記憶體 | 程式設計師手動管理 | malloc/free 或 new/delete |
int a = 0; // 全域初始化區
char *p1; // 全域未初始化區 (BSS)
main() {
int b; // 堆疊
char s[] = "abc"; // 堆疊 (陣列內容複製自常數區)
char *p2; // 堆疊 (指標變數本身)
char *p3 = "123456"; // "123456\0" 在常數區,p3 在堆疊
static int c = 0; // 全域/靜態初始化區
p1 = (char *)malloc(10); // 堆區配置 10 bytes
p2 = (char *)malloc(20); // 堆區配置 20 bytes
strcpy(p1, "123456"); // 複製常數區字串到堆區
}
int b; 編譯器自動在堆疊預留空間malloc,C++ 用 new,需指定大小free/delete 使用VirtualAlloc 直接在進程位址空間保留/提交頁面,繞過堆管理器,速度最快、最彈性,但使用最複雜char a = 1;
char c[] = "1234567890"; // 堆疊陣列
char *p = "1234567890"; // 指向常數區/堆
a = c[1]; // 反組譯:直接 [ebp-offset] 位址存取
a = p[1]; // 反組譯:先載入 p 到暫存器,再 [reg+offset] 間接存取 → 較慢
堆疊陣列存取為直接位址運算,指標間接存取需額外載入指標值,故堆疊略快。
static 區域變數不入堆疊